I64 sc_1, sc_2;

#define DROPS_NUM                       0x2000

class Drop
{
        I32 x, y;
} drops[DROPS_NUM];

CDC *cur_dc;

U0 DrawFrame(CTask *task, CDC *dc)
{
        I64 w = task->pix_width, h = task->pix_height, cx = w >> 1, cy = h >> 1;

        dc->color = LTRED;
        GrLine(dc, cx - 20, cy - 50, cx, cy - 150);
        GrLine(dc, cx + 20, cy - 50, cx, cy - 150);

        dc->color = LTRED;
        GrLine(dc, cx - 100, cy - 100, cx, cy);
        GrLine(dc, cx + 100, cy - 100, cx, cy);
        if (Bt(kbd.down_bitmap, sc_1))
        {
                dc->color = WHITE;
                GrRect(dc, cx - 2, cy - 2, 5, 5);
        }
        dc->color = BLACK;
        GrPrint(dc, cx + 10, cy, "Press '1'");

        dc->color = LTRED;
        GrRect(dc, cx - 20, cy + 60, 41, 21);

        dc->color = LTRED;
        GrLine(dc, cx - 200, cy, cx, cy + 100);
        GrLine(dc, cx + 200, cy, cx, cy + 100);
        if (Bt(kbd.down_bitmap, sc_2))
        {
                dc->color = WHITE;
                GrRect(dc, cx - 2, cy + 100 - 2, 5, 5);
        }
        dc->color = BLACK;
        GrPrint(dc, cx + 10, cy + 100, "Press '2'");

        dc->color = LTRED;
        GrLine(dc, cx + 400, cy + 100, cx - 250, cy + 200);
}

U0 DrawDrops(CTask *, CDC *dc)
{
        I64 i;

        dc->color = BLUE;
        for (i = 0; i < DROPS_NUM; i++)
                if (drops[i].y >= 0 && GrPeek(dc, drops[i].x, drops[i].y) == WHITE)
                        GrPlot(dc, drops[i].x, drops[i].y);
}

U0 UpdateCurBase(CTask *task, CDC *dc)
{
        cur_dc->color = ROP_EQU;
        dc->flags |= DCF_NO_TRANSPARENTS;
        GrBlot(cur_dc, -task->pix_left - task->scroll_x, -task->pix_top - task->scroll_y, dc);
        dc->flags &= ~DCF_NO_TRANSPARENTS;
}

U0 DrawIt(CTask *task, CDC *dc)
{
        DrawFrame(task, dc);
        DrawDrops(task, dc);
        UpdateCurBase(task, dc);
}

U0 AnimateTask(I64)
{
        I64 i, j, cur_drop = 0, c1, c2, x0, y0, x1, y1, w, h;

        while (TRUE)
        {
                w = Fs->parent_task->pix_width;
                h = Fs->parent_task->pix_height;

                for (i = 0; i < 2; i++)
                {
                        j = 0;
                        do
                        {
                                if (++cur_drop >= DROPS_NUM)
                                        cur_drop = 0;
                                if (drops[cur_drop].y < 0)
                                        break;
                                j++;
                        }
                        while (j <= DROPS_NUM);

                        drops[cur_drop].x = RandU32%w;
                        drops[cur_drop].y = 0;
                }

                for (i = 0; i < DROPS_NUM; i++)
                {
                        if (drops[i].y >= 0)
                        {
                                if (drops[i].y >= h - 1)
                                        drops[i].y = -I32_MAX;
                                else
                                {
                                        x0 = x1 = drops[i].x;
                                        y0 = y1 = drops[i].y;
                                        if (GrPeek(cur_dc, x0, y0 + 1) == WHITE)
                                                y1++;
                                        else
                                        {
                                                c1 = GrPeek(cur_dc, x0 + 1, y0);
                                                c2 = GrPeek(cur_dc, x0 - 1, y0);
                                                if (c1 == WHITE && c2 != WHITE)
                                                        x1++;
                                                else if (c2 == WHITE && c1 != WHITE)
                                                        x1--;
                                                else if (c1 == WHITE && c2 == WHITE)
                                                {
                                                        c1 = GrPeek(cur_dc, x0 + 1, y0 + 1);
                                                        c2 = GrPeek(cur_dc, x0 - 1, y0 + 1);
                                                        if (c1 == WHITE && c2 != WHITE)
                                                                x1++;
                                                        else if (c2 == WHITE && c1 != WHITE)
                                                                x1--;
                                                        else if (RandI16 >= 0)
                                                                x1++;
                                                        else
                                                                x1--;
                                                }
                                                if (GrPeek(cur_dc, x1, y1 + 1) == WHITE)
                                                        y1++;
                                        }
                                        if (GrPeek(cur_dc, x0, y0) == BLUE)
                                        {
                                                cur_dc->color = WHITE;
                                                GrPlot(cur_dc, x0, y0);
                                        }
                                        cur_dc->color = BLUE;
                                        GrPlot(cur_dc, x1, y1);
                                        drops[i].x = x1;
                                        drops[i].y = y1;
                                }
                        }
                }
                Sleep(10);
        }
}

U0 Init()
{
        I64 i;

        MemSet(drops, 0, sizeof(drops));
        for (i = 0; i < DROPS_NUM;i ++)
                drops[i].y = -I32_MAX;
}

U0 RainDrops()
{
        I64 ch, sc;

        MenuPush(       "File {"
                                "  Abort(,CH_SHIFT_ESC);"
                                "  Exit(,CH_ESC);"
                                "}"
                                "Play {"
                                "  Restart(,'\n');"
                                "  OpenUpper(,'1');"
                                "  OpenLower(,'2');"
                                "}"
                                );
        SettingsPush; //See SettingsPush
        AutoComplete;
        WinBorder;
        WinMax;
        DocCursor;
        DocClear;
        cur_dc = DCNew(GR_WIDTH, GR_HEIGHT);
        sc_1 = Char2ScanCode('1');
        sc_2 = Char2ScanCode('2');
        Init;
        Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs);
        Fs->draw_it              = &DrawIt;
        try
        {
                do
                        switch (ch = KeyGet(&sc))
                        {
                                case '\n':
                                        Init;
                                        break;
                        }
                while (ch != CH_ESC && ch != CH_SHIFT_ESC);
        }
        catch
                PutExcept;
        SettingsPop;
        MenuPop;
        DCDel(cur_dc);
}

RainDrops;