// life.c
// Transcribe BASIC LIFE.bas to C
// by Andre Adrian, DL1ADR, 2026-05-03

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define XSZ 50  // grid size rows
#define YSZ 70  // grid size columns
#define DD 0    // is death, becomes death
#define LL 1    // is live, becomes live
#define DL 2    // is death, becomes live
#define LD 3    // is live, becomes death

void TAB(int x) {
    while(--x) {
        printf(" ");
    }
}

int main() {                                                // REM LIFE.bas
    char A[XSZ+1][YSZ+1], B[XSZ+1][40];                     // DIM A(26,70),B$(24)
    memset(A, 0, sizeof(A));                                // zero A
    int C=0, G=0, P=0, E=0;                                 // C=0:G=0:P=0:E=0
    TAB(34); printf("LIFE\n");                              // PRINT TAB(34);"LIFE"
    TAB(15); printf("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"
                    "\n\n"
                    "ENTER YOUR PATTERN:\n");
    for (;;) {                                              // L80:
        fgets(B[C], sizeof(B[0]), stdin);                   // INPUT B$(C)
        *strchr(B[C], '\n')='\0';                           // remove \n
        if (strstr(B[C], "DONE")) {                         // IF B$(C)="DONE" THEN
            break;                                          //   L110
        }
        ++C;                                                // C=C+1
    }                                                       // GOTO L80
                                                            // L110:
    --C; unsigned L=0;                                      // C=C-1:L=0
    for(int X=0; X<=C-1; ++X) {                             // FOR X=0 TO C-1
        if (strlen(B[X])>L)                                 //   IF LEN(B$(X))>L THEN
            L=strlen(B[X]);                                 //     L=LEN(B$(X))
    }                                                       // NEXT X
    int X1=XSZ/2-C/2, X2=X1+C;                              // X1=13-INT(C/2):X2=X1+C
    int Y1=YSZ/2-L/2, Y2=Y1+L;                              // Y1=35-INT(L/2):Y2=Y1+L
    for (int X=0; X<=C; ++X) {                              // FOR X=0 TO C
        for (unsigned Y=0; Y<strlen(B[X]); ++Y) {           //   FOR Y=1 TO LEN(B$(X))
            if (B[X][Y]=='*') {                             //     IF MID$(B$(X),Y,1)="*" THEN
                A[X1+X][Y1+Y]=1; ++P;                       //       A(X1+X,Y1+Y)=1:P=P+1
            }
        }                                                   //   NEXT Y
    }                                                       // NEXT X
    printf("\n\n");                                         // PRINT:PRINT
    for(;;) {                                               // L230:
        int X4=2, X3=XSZ-2, Y4=2, Y3=YSZ-2;                 // X4=2:X3=24:Y4=2:Y3=68
        for (int X=1; X<=X1-1; ++X) printf("\n");           // FOR X=1 TO X1-1:PRINT:NEXT X
        printf("\n");                                       // BASIC FOR-NEXT at least loops once
        for (int X=X1; X<=X2; ++X) {                        // FOR X=X1 TO X2
            TAB(Y1);                                        //   PRINT TAB(Y1);
            for (int Y=Y1; Y<=Y2; ++Y) {                    //   FOR Y=Y1 TO Y2
                if (A[X][Y]==DD || A[X][Y]==LD) {           //     IF A(X,Y)=0 OR A(X,Y)=3 THEN
                    A[X][Y]=DD; printf(" "); continue;      //       A(X,Y)=0:PRINT " ";:GOTO L340
                }
                A[X][Y]=LL; printf("*");                    //     A(X,Y)=1:PRINT "*";
                if (X<X3) X3=X;                             //     IF X<X3 THEN X3=X
                if (X>X4) X4=X;                             //     IF X>X4 THEN X4=X
                if (Y<Y3) Y3=Y;                             //     IF Y<Y3 THEN Y3=Y
                if (Y>Y4) Y4=Y;                             //     IF Y>Y4 THEN Y4=Y
                                                            // L340:
            }                                               //   NEXT Y
            printf("\n");                                   //   PRINT
        }                                                   // NEXT X
        for (int X=X2+1; X<=XSZ-1; ++X) printf("\n");       // FOR X=X2+1 TO 24:PRINT:NEXT X
        printf("\n");                                       // BASIC FOR-NEXT at least loops once
        printf("GENERATION: %d\t\tPOPULATION: %d ", G, P);  // PRINT "GENERATION:";G,"POPULATION:";P;
        if (E) printf("INVALID %d", E);                     // IF E THEN PRINT "INVALID";E;
        if (P==0) break;                                    // IF P=0 THEN STOP
        sleep(1);                                           // slow down computer
        X1=X3; X2=X4; Y1=Y3; Y2=Y4; ++G; P=0; E=0;          // X1=X3:X2=X4:Y1=Y3:Y2=Y4:G=G+1:P=0:E=0
        if (X1<2) { X1=2; E=1; }                            // IF X1<2 THEN X1=2:E=1
        if (X2>XSZ-2) { X2=XSZ-2; E+=2; }                   // IF X2>24 THEN X2=24:E=2
        if (Y1<2) { Y1=2; E+=4; }                           // IF Y1<2 THEN Y1=2:E=3
        if (Y2>YSZ-2) { Y2=YSZ-2; E+=8; }                   // IF Y2>68 THEN Y2=68:E=4
        for (int X=X1-1; X<=X2+1; ++X) {                    // FOR X=X1-1 TO X2+1
            for (int Y=Y1-1; Y<=Y2+1; ++Y) {                //   FOR Y=Y1-1 TO Y2+1
                C=0;                                        //     C=0
                for (int I=X-1; I<=X+1; ++I) {              //     FOR I=X-1 TO X+1
                    for (int J=Y-1; J<=Y+1; ++J) {          //       FOR J=Y-1 TO Y+1
                        if (A[I][J]&1)                      //         IF A(I,J) AND 1 THEN
                            ++C;                            //           C=C+1
                    }                                       //       NEXT J
                }                                           //     NEXT I
                if (A[X][Y]==DD) goto L570;                 //     IF A(X,Y)=0 THEN L570
                if (C<3 || C>4) {                           //     IF C<3 OR C>4 THEN
                    A[X][Y]=LD; continue;                   //       A(X,Y)=3:GOTO L580
                }
                ++P; continue;                              //     P=P+1:GOTO L580
L570:                                                       // L570:
                if(C==3) {                                  //     IF C=3 THEN
                    A[X][Y]=DL; ++P;                        //       A(X,Y)=2:P=P+1
                }
                                                            // L580:
            }                                               //   NEXT Y
        }                                                   // NEXT X
        --X1; --Y1; ++X2; ++Y2;                             // X1=X1-1:Y1=Y1-1:X2=X2+1:Y2=Y2+1
    }                                                       // GOTO L230
}                                                           // END
