//Conway's Game of Life

CDC *dc[2]; //double buf
I64  cur_dc, ;
Bool restart;

U0 DrawIt(CTask *, CDC *dc2)
{
        dc[cur_dc]->flags |= DCF_NO_TRANSPARENTS;
        GrBlot(dc2, 0, 0, dc[cur_dc]);
}

U0 AnimateTask(I64)
{
        I64 x, y, x1, y1, count, next_dc;

        while (TRUE)
        {
                next_dc = cur_dc ^ 1;
start_over:
                restart = FALSE;
                DCClear(dc[next_dc]);
                for (y = 1; y < Fs->parent_task->pix_height - 1; y++)
                {
                        for (x = 1; x < Fs->parent_task->pix_width - 1; x++)
                        {
                                count = 0;
                                for (y1 = y - 1; y1 <= y + 1; y1++)
                                        for (x1 = x - 1; x1 <= x + 1; x1++)
                                                if (GrPeek(dc[cur_dc], x1, y1) == GREEN)
                                                        count++;
                                if (restart)
                                        goto start_over;
                                if (GrPeek(dc[cur_dc], x, y) == GREEN)
                                {
                                        if (count == 3)
                                        {
                                                dc[next_dc]->color = GREEN;
                                                GrPlot(dc[next_dc], x, y);
                                        }
                                }
                                else
                                {
//                                      if (count == 3) //Use this for the classic rules
                                        if (count == 2)
                                        {
                                                dc[next_dc]->color = GREEN;
                                                GrPlot(dc[next_dc], x, y);
                                        }
                                }
                        }
                        Yield;
                }
                Sleep(50);
                cur_dc = next_dc;
        }
}

public U0 Life()
{
        I64 message_code, count, x1, y1, x2, y2, arg1, arg2;

        dc[0] = DCNew(GR_WIDTH, GR_HEIGHT);
        dc[1] = DCNew(GR_WIDTH, GR_HEIGHT);
        cur_dc = 0;
        restart = FALSE;

        SettingsPush; //See SettingsPush
        AutoComplete;
        WinBorder;
        WinMax;
        DocClear;
        DCFill;

        Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs);
        Fs->draw_it              = &DrawIt;
        Fs->win_inhibit  = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_BORDER;
        do
        {
                message_code = MessageGet(&arg1, &arg2, 1 << MESSAGE_KEY_DOWN + 1 << MESSAGE_MS_L_DOWN);
                switch (message_code)
                {
                        case MESSAGE_MS_L_DOWN:
                                x1 = arg1;
                                y1 = arg2;
                                x2 = arg1;
                                y2 = arg2;
                                count = 0;
                                while (message_code != MESSAGE_MS_L_UP)
                                {
                                        restart = TRUE;
                                        dc[cur_dc]->color = GREEN;
                                        dc[cur_dc]->thick = 0.04 * mouse.speed;
                                        GrLine3(dc[cur_dc], x1, y1, 0, x2, y2, 0);
                                        restart = TRUE;
                                        message_code = MessageGet(&arg1, &arg2, 1 << MESSAGE_MS_L_UP + 1 << MESSAGE_MS_MOVE);
                                        x1 = x2;
                                        y1 = y2;
                                        x2 = arg1;
                                        y2 = arg2;
                                }
                                GrLine3(dc[cur_dc], x1, y1, 0, x2, y2, 0);
                                break;

                        case MESSAGE_KEY_DOWN:
                                break;
                }
        }
        while (message_code != MESSAGE_KEY_DOWN || !arg1);

        MessageGet(,, 1 << MESSAGE_KEY_UP);
        SettingsPop;
        DCFill;
        DCDel(dc[0]);
        DCDel(dc[1]);
}

Life;