🚩 Home / 💻 Projects / LIFE / LIFE.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string>

#define cls()           printf("\033[2J")
#define hide()          printf("\033[?25l")
#define show()          printf("\033[?25h")
#define gotoxy(x, y)    printf("%c[%d;%df", 0x1B, (x), (y))
#define block(x)        printf("\033[%dm%d\033[0m", colors[(x)], (x))
#define setxy()         gotoxy(0, 1)
#define draw()          output(size.ws_row, size.ws_col)
#define locateP()       gotoxy(i - x_axis - 1, j - y_axis)
#define setTitle()      max_life = max(max_life, life); printf("\033]2;%d * Life\007", life)
#define max(a, b)       ((a > b) ? (a) : (b))
#define min(a, b)       ((a < b) ? (a) : (b))

#define SPACESHIP()     space[2][3] = space[3][4] = space[4][4] = space[4][3] = space[4][2] = 1

//                         0   1   2   3   4   5   6   7   8
const int colors[10] = {30, 31, 34, 35, 33, 32, 36, 37, 37};
const int MSIZE = 200;
const int delta_x = 7, delta_y = 10;

struct winsize size;
bool space[MSIZE + 10][MSIZE + 10];
bool chg[MSIZE + 10][MSIZE + 10];
bool auto_gen = false;
int o_row = 0, o_col = 0;
int x_axis = 0, y_axis = 0;
int life = 0, max_life = 0, tot_life = 0;
int PTime = 0;
int ms = 1;

int kbhit();
int cnt(int, int);
void end();
void count_life();
void randomize(int);
void generate();
void rule();
void output(int, int);

int main()
{
    hide();
    srand((unsigned)time(NULL));
    memset(space, 0, sizeof(space));
    ioctl(STDIN_FILENO, TIOCGWINSZ, &size);
    //your settings here:
    // SPACESHIP();
    randomize(30);
    //
    count_life();
    while (true)
    {
        if (kbhit())
        {
            int ch = getchar();
            fflush(stdin);
            switch (ch)
            {
            case 10:
                generate();
                break;
            case 'w':
            case 'W':
                x_axis = max(x_axis - delta_x, 0);
                draw();
                break;
            case 's':
            case 'S':
                x_axis = min(x_axis + delta_x, MSIZE - 2);
                draw();
                break;
            case 'a':
            case 'A':
                y_axis = max(y_axis - delta_y, 0);
                draw();
                break;
            case 'd':
            case 'D':
                y_axis = min(y_axis + delta_y, MSIZE - 2);
                draw();
                break;
            case 'f':
            case 'F':
                auto_gen = !auto_gen;
                break;
            case 'e':
            case 'E':
                end();
                exit(0);
            }
        }
        if (auto_gen)
        {
            generate();
            usleep(ms * 1000);
        }
        if (size.ws_col != o_col || size.ws_row != o_row)
        {
            draw();
            o_col = size.ws_col;
            o_row = size.ws_row;
        }
        ioctl(STDIN_FILENO, TIOCGWINSZ, &size);
    }
    show();
    return 0;
}

void rule()
{
    memset(chg, 0, sizeof(chg));
    for (int i = 1; i <= MSIZE; i++)
        for (int j = 1; j <= MSIZE; j++)
        {
            int t = cnt(i, j);
            if (space[i][j])
                chg[i][j] = (t < 2 || t > 3);
            else
                chg[i][j] = (t == 3);
        }
}

void generate()
{
    PTime++;
    rule();
    for (int i = 1; i <= MSIZE; i++) //apply changes
        for (int j = 1; j <= MSIZE; j++)
            if (chg[i][j])
            {
                space[i][j] = !space[i][j];
                life += space[i][j] ? 1 : -1;
                tot_life += space[i][j];
            }

    int i_max = min(size.ws_row + x_axis, MSIZE);
    int j_max = min(size.ws_col + y_axis, MSIZE);
    for (int i = x_axis + 1; i <= i_max; i++)
        for (int j = y_axis + 1; j <= j_max; j++)
            if (chg[i][j] || chg[i - 1][j] || chg[i + 1][j] ||
                chg[i][j - 1] || chg[i - 1][j - 1] || chg[i + 1][j - 1] ||
                chg[i][j + 1] || chg[i - 1][j + 1] || chg[i + 1][j + 1])
            {
                chg[i][j] = 0;
                locateP();
                block(cnt(i, j) * space[i][j]);
            }
    setTitle();
    setxy();
}

void output(int x, int y)
{
    cls();
    int i_max = min(size.ws_row + x_axis, MSIZE);
    int j_max = min(size.ws_col + y_axis, MSIZE);
    for (int i = x_axis + 1; i <= i_max; i++)
    {
        for (int j = y_axis + 1; j <= j_max; j++)
        {
            locateP();
            block(cnt(i, j) * space[i][j]);
        }
        printf("\n");
    }
}

void count_life()
{
    life = 0;
    for (int i = 1; i <= MSIZE; i++)
        for (int j = 1; j <= MSIZE; j++)
            life += space[i][j];
    tot_life = life;
    setTitle();
}

int cnt(int x, int y)
{
    int ans = 0;
    if (space[x - 1][y - 1])
        ans++;
    if (space[x - 1][y])
        ans++;
    if (space[x - 1][y + 1])
        ans++;
    if (space[x + 1][y - 1])
        ans++;
    if (space[x + 1][y])
        ans++;
    if (space[x + 1][y + 1])
        ans++;
    if (space[x][y - 1])
        ans++;
    if (space[x][y + 1])
        ans++;
    return ans;
}

void randomize(int x)
{
    for (int i = 1; i <= MSIZE; i++)
        for (int j = 1; j <= MSIZE; j++)
            if (rand() % 100 < 100 - x)
                space[i][j] = 0;
            else
                space[i][j] = 1;
}

int kbhit()
{
    struct termios oldt, newt;
    int ch;
    int oldf;
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);
    if (ch != EOF)
    {
        ungetc(ch, stdin);
        return 1;
    }
    return 0;
}

void end()
{
    cls();
    setxy();
    int mark = rand() % 10000, bit = 0, cpy = tot_life;
    while (cpy)
    {
        cpy /= 10;
        bit++;
    }
    show();
    printf("\033[36m--===Life and Death===--\033[0m\n");
    printf("\033[32mCosmos #%04d\033[0m Destoried,\n", mark);
    printf("which has Developed for \033[33m%d\033[0m years.\n", PTime);
    printf("\033[33m%*d\033[0m Creature%s Had Endured the Torment of the END.\n", bit, life, life ? "s" : "");
    printf("\033[33m%*d\033[0m Creature%s Once Existed at the Same Time.\n", bit, max_life, max_life ? "s" : "");
    printf("\033[33m%*d\033[0m Creature%s Once Appeared on \033[32mCosmos #%04d\033[0m.\n\n", bit, tot_life, tot_life ? "s" : "", mark);
    printf("Waiting for another Cosmos...\n");
}
DOWNLOAD