RegDefault("ZealOS/DunGen", "F64 best_score=9999;\n");
RegExe("ZealOS/DunGen");

//Set snap to 4 and width to 4
//if you edit this map.

//Don't forget to change the
//starting pos.


<1>/* Graphics Not Rendered in HTML */









<2>/* Graphics Not Rendered in HTML */



<3>/* Graphics Not Rendered in HTML */

 
<4>/* Graphics Not Rendered in HTML */

<5>/* Graphics Not Rendered in HTML */

<6>/* Graphics Not Rendered in HTML */

<7>/* Graphics Not Rendered in HTML */

<8>/* Graphics Not Rendered in HTML */

<9>/* Graphics Not Rendered in HTML */

<10>/* Graphics Not Rendered in HTML */


//These are indexed by color #.
//See COLORS.

U8 *tiles1[16]={NULL, <7> , <5> , NULL, NULL, NULL, NULL, NULL, <6> , NULL, NULL, NULL, NULL, NULL, NULL, NULL};

U8 *tiles2[16]={NULL, <8> , <5> , NULL, NULL, NULL, NULL, NULL, <6> , NULL, NULL, NULL, NULL, NULL, NULL, NULL};

#define SCREEN_SCALE            24
#define SCREEN_WIDTH            24
#define SCREEN_HEIGHT           24
I64 screen_x, screen_y;

#define MAP_SCALE                       4
I64 map_width, map_height;
U8 *map = NULL;

I64  man_x, man_y, man_dx, man_dy;
Bool man_attack;
F64  man_attack_t0;

#define MONSTERS_NUM            10
I64 monsters_left;
class Monster
{
        I64  x, y, dx, dy;
        Bool dead, pad[7];

} monsters[MONSTERS_NUM];

F64 t0, tf;

#define LOS_SCALE                       4

Bool LOSPlot(U8 *, I64 x, I64 y, I64)
{
        if (!map[(y / LOS_SCALE) * map_width + (x / LOS_SCALE)])
                return FALSE;
        else
                return TRUE;
}

Bool LOS(I64 x1, I64 y1, I64 x2, I64 y2)
{//Line of sight
        return Line(NULL, x1 * LOS_SCALE + LOS_SCALE / 2, y1 * LOS_SCALE + LOS_SCALE / 2, 0, 
                                          x2 * LOS_SCALE + LOS_SCALE / 2, y2 * LOS_SCALE + LOS_SCALE / 2, 0, &LOSPlot);
}

U0 DrawIt(CTask *task, CDC *dc)
{
        CDC             *dc_t = DCAlias(gr.dc2, task);
        I64              i, x, y, xx, yy, x1, y1, z1, color, 
                         cx = task->pix_width  / 2, 
                         cy = task->pix_height / 2;
        CD3I32   poly[4];
        U8         **_tiles;
        F64              tt;
        Monster *tmpm;

        if (Blink(5))
                _tiles = tiles1;
        else
                _tiles = tiles2;

        Mat4x4RotX(dc_t->r, 60 * 2 * pi / 360);
        Mat4x4RotZ(dc_t->r, 15 * 2 * pi / 360);
        DCMat4x4Set(dc_t, dc_t->r);
        dc_t->x = task->pix_width  / 2;
        dc_t->y = task->pix_height / 2;
        dc_t->flags |= DCF_TRANSFORMATION;

        //You could make it much more efficient
        //if you did it like ::/Demo/Games/BigGuns.CC
        //with a CDC.

        for (y = -SCREEN_HEIGHT / 2; y < SCREEN_HEIGHT / 2; y++)
        {
                yy = y + screen_y;
                if (0 <= yy < map_height)
                        for (x = -SCREEN_WIDTH / 2; x < SCREEN_WIDTH / 2; x++)
                        {
                                xx = x + screen_x;
                                if (0 <= xx < map_width)
                                {
                                        if ((color = map[yy * map_width + xx]) && LOS(xx, yy, man_x, man_y))
                                        {
                                                if (_tiles[color])
                                                {
                                                        x1 = x * SCREEN_SCALE;
                                                        y1 = y * SCREEN_SCALE;
                                                        z1 = 0;
                                                        DCTransform(dc_t, &x1, &y1, &z1);
                                                        Sprite3(dc, x1, y1, z1, _tiles[color]);
                                                }
                                                else
                                                {//If no tile defined, do solid color.
                                                        poly[0].x = x * SCREEN_SCALE;
                                                        poly[0].y = y * SCREEN_SCALE;
                                                        poly[0].z = 0;
                                                        poly[1].x = (x + 1) * SCREEN_SCALE - 1;
                                                        poly[1].y = y * SCREEN_SCALE;
                                                        poly[1].z = 0;
                                                        poly[2].x = (x + 1) * SCREEN_SCALE;
                                                        poly[2].y = (y + 1) * SCREEN_SCALE - 1;
                                                        poly[2].z = 0;
                                                        poly[3].x = x * SCREEN_SCALE - 1;
                                                        poly[3].y = (y + 1) * SCREEN_SCALE - 1;
                                                        poly[3].z = 0;
                                                        dc_t->color = color;
                                                        GrFillPoly3(dc_t, 4, poly);
                                                }
                                        }
                                }
                        }
        }

        for (y = -SCREEN_HEIGHT / 2; y < SCREEN_HEIGHT / 2; y++)
        {
                yy = y + screen_y;
                if (0 <= yy < map_height)
                        for (x = -SCREEN_WIDTH / 2; x < SCREEN_WIDTH / 2; x++)
                        {
                                xx = x + screen_x;
                                if (0 <= xx < map_width)
                                {
                                        if (!map[yy * map_width + xx])
                                        {
                                                if (yy + 1 < map_height && LOS(xx, yy + 1, man_x, man_y))
                                                {
                                                        x1 = x * SCREEN_SCALE;
                                                        y1 = y * SCREEN_SCALE;
                                                        z1 = 0;
                                                        DCTransform(dc_t, &x1, &y1, &z1);
                                                        Sprite3(dc, x1, y1, z1, <9>);
                                                }
                                                if (xx + 1 < map_width && LOS(xx + 1, yy, man_x, man_y))
                                                {
                                                        x1 = x * SCREEN_SCALE;
                                                        y1 = y * SCREEN_SCALE;
                                                        z1 = 0;
                                                        DCTransform(dc_t, &x1, &y1, &z1);
                                                        Sprite3(dc, x1, y1, z1, <10>);
                                                }
                                        }
                                }
                        }
        }

        for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++)
                if (!tmpm->dead && LOS(tmpm->x, tmpm->y, man_x, man_y))
                {
                        x1 = (tmpm->x - screen_x) * SCREEN_SCALE + SCREEN_SCALE / 2;
                        y1 = (tmpm->y - screen_y) * SCREEN_SCALE + SCREEN_SCALE / 2;
                        z1 = 0;
                        DCTransform(dc_t, &x1, &y1, &z1);
                        if (tmpm->dx < 0) {
                                dc->flags |= DCF_SYMMETRY|DCF_JUST_MIRROR;
                                DCSymmetrySet(dc, x1, y1, x1, y1 + 1);
                        }
                        else
                                dc->flags &= ~(DCF_SYMMETRY | DCF_JUST_MIRROR);
                        Sprite3(dc, x1, y1, z1, <4>);
                }

        x1 = (man_x - screen_x) * SCREEN_SCALE + SCREEN_SCALE / 2;
        y1 = (man_y - screen_y) * SCREEN_SCALE + SCREEN_SCALE / 2;
        z1 = 0;
        if (tS - man_attack_t0 < 0.2)
        {
                x1 += Tri(tS - man_attack_t0, 0.2) * SCREEN_SCALE * man_dx;
                y1 += Tri(tS - man_attack_t0, 0.2) * SCREEN_SCALE * man_dy;
                if (man_dy != 1)
                        y1 -= Saw(tS - man_attack_t0, 0.2) * SCREEN_SCALE;
        }
        DCTransform(dc_t, &x1, &y1, &z1);
        if (man_dx < 0)
        {
                dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR;
                DCSymmetrySet(dc, x1, y1, x1, y1 + 1);
        }
        else
                dc->flags &= ~(DCF_SYMMETRY | DCF_JUST_MIRROR);

        if (tS - man_attack_t0 < 0.2)
                Sprite3(dc, x1, y1, z1, <3>);
        else
                Sprite3(dc, x1, y1, z1, <2>);

        DCDel(dc_t);

        if (tf)
        {
                dc->color = LTRED;
                if (Blink)
                        GrPrint(dc, cx - (FONT_WIDTH * 14) / 2, cy - FONT_HEIGHT / 2, "Game Completed");
                tt = tf;
        }
        else
        {
                dc->color = LTGREEN;
                tt = tS;
        }
        GrPrint(dc, 0, 0, "Enemy:%d Time:%3.2f Best:%3.2f", monsters_left, tt - t0, best_score);
}

U0 Attack()
{
        I64              i;
        Monster *tmpm;

        man_attack_t0 = tS;
        Noise(100, 53, 74);
        for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++)
        {
                if (!tmpm->dead && man_x + man_dx == tmpm->x && man_y + man_dy == tmpm->y)
                {
                        tmpm->dead = TRUE;
                        if (!--monsters_left)
                        {
                                tf = tS;
                                if (tf - t0 < best_score)
                                        best_score = tf - t0;
                        }
                }
        }
}

U0 Init()
{
        I64              i, x, y;
        CDC             *dc;
        Monster *tmpm;

        dc = Sprite2DC(<1>);
        map_width  = dc->width  / MAP_SCALE;
        map_height = dc->height / MAP_SCALE;
        Free(map);
        map = MAlloc(map_width * map_height * sizeof(U8));
        for (y = 0; y < map_height; y++)
                for (x = 0; x < map_width; x++)
                        map[y * map_width + x] = GrPeek(dc, x * MAP_SCALE, y * MAP_SCALE);
        DCDel(dc);

        man_attack_t0 = 0;
        man_attack = FALSE;
        man_x = 0;
        man_y = 4;
        man_dx = 0;
        man_dy = 0;
        screen_x = 0;
        screen_y = 0;
        for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++)
        {
                tmpm->dead      = FALSE;
                tmpm->dx        = 0;
                tmpm->dy        = 0;
                do
                {
                        tmpm->x = RandU64 % (map_width  - 2) + 1;
                        tmpm->y = RandU64 % (map_height - 2) + 1;
                }
                while (!map[(tmpm->y) * map_width + tmpm->x]);
        }
        monsters_left = MONSTERS_NUM;
        tf = 0;
        t0 = tS;
}

U0 CleanUp()
{
        Free(map);
        map = NULL;
}

U0 AnimateTask(I64)
{
        I64              i, x, y, dx, dy;
        Monster *tmpm;

        while (TRUE)
        {
                for (i = 0, tmpm = monsters; i < MONSTERS_NUM; i++, tmpm++)
                        if (!tmpm->dead)
                        {
                                dx = RandU16 % 3 - 1;
                                dy = RandU16 % 3 - 1;
                                x = tmpm->x + dx;
                                y = tmpm->y + dy;
                                if (0 <= x < map_width && 0 <= y < map_height && map[y * map_width + x])
                                {
                                        tmpm->x  = x;
                                        tmpm->y  = y;
                                        tmpm->dx = dx;
                                        tmpm->dy = dy;
                                }
                        }
                Sleep(1000);
        }
}

U0 DunGen()
{
        I64 ch, sc;

        MenuPush(
                                "File {"
                                "  Abort(,CH_SHIFT_ESC);"
                                "  Exit(,CH_ESC);"
                                "}"
                                "Play {"
                                "  Restart(,'\n');"
                                "  Up(,,SC_CURSOR_UP);"
                                "  Down(,,SC_CURSOR_DOWN);"
                                "  Left(,,SC_CURSOR_LEFT);"
                                "  Right(,,SC_CURSOR_RIGHT);"
                                "  Attack(,CH_SPACE);"
                                "}"
                                );

        SettingsPush; //See SettingsPush
        Fs->text_attr = BLACK << 4 + WHITE;
        AutoComplete;
        WinBorder;
        WinMax;
        DocCursor;
        DocClear;
        Init;
        Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs);
        Fs->draw_it              = &DrawIt;

        try
        {
                while (TRUE)
                {
                        switch (MessageGet(&ch, &sc, 1 << MESSAGE_KEY_DOWN | 1 << MESSAGE_KEY_UP))
                        {
                                case MESSAGE_KEY_DOWN:
                                        switch (ch)
                                        {
                                                case '\n':
                                                        Init;
                                                        break;

                                                case CH_SPACE:
                                                        man_attack = TRUE;
                                                        break;

                                                case CH_ESC:
                                                case CH_SHIFT_ESC:
                                                        goto dg_done;

                                                case 0:
                                                        switch (sc.u8[0])
                                                        {
                                                                case SC_CURSOR_RIGHT:
                                                                        if (man_attack)
                                                                        {
                                                                                man_dx = 1;
                                                                                man_dy = 0;
                                                                                Attack;
                                                                        }
                                                                        else
                                                                                if (man_x + 1 < map_width && map[man_y * map_width + (man_x + 1)] == DKGRAY)
                                                                                {
                                                                                        man_x++;
                                                                                        if (man_x - screen_x > SCREEN_WIDTH / 2 - 3)
                                                                                        {
                                                                                                screen_x += SCREEN_WIDTH / 2;
                                                                                                if (screen_x + SCREEN_WIDTH / 2 > map_width)
                                                                                                        screen_x = map_width - SCREEN_WIDTH / 2;
                                                                                        }
                                                                                }
                                                                        break;

                                                                case SC_CURSOR_LEFT:
                                                                        if (man_attack)
                                                                        {
                                                                                man_dx = -1;
                                                                                man_dy = 0;
                                                                                Attack;
                                                                        }
                                                                        else
                                                                                if (man_x - 1 >= 0 && map[man_y * map_width + (man_x - 1)] == DKGRAY)
                                                                                {
                                                                                        man_x--;
                                                                                        if (man_x - screen_x < -SCREEN_WIDTH / 2 + 3)
                                                                                        {
                                                                                                screen_x -= SCREEN_WIDTH / 2;
                                                                                                if (screen_x - SCREEN_WIDTH / 2 < 0)
                                                                                                        screen_x = SCREEN_WIDTH / 2;
                                                                                        }
                                                                                }
                                                                        break;

                                                                case SC_CURSOR_UP:
                                                                        if (man_attack)
                                                                        {
                                                                                man_dx = 0;
                                                                                man_dy = -1;
                                                                                Attack;
                                                                        }
                                                                        else
                                                                                if (man_y - 1 >= 0 && map[(man_y - 1) * map_width + man_x] == DKGRAY)
                                                                                {
                                                                                        man_y--;
                                                                                        if (man_y - screen_y < -SCREEN_HEIGHT / 2 + 3)
                                                                                        {
                                                                                                screen_y -= SCREEN_HEIGHT / 2;
                                                                                                if (screen_y - SCREEN_HEIGHT / 2 < 0)
                                                                                                        screen_y = SCREEN_HEIGHT / 2;
                                                                                        }
                                                                                }
                                                                        break;

                                                                case SC_CURSOR_DOWN:
                                                                        if (man_attack)
                                                                        {
                                                                                man_dx = 0;
                                                                                man_dy = 1;
                                                                                Attack;
                                                                        }
                                                                        else
                                                                                if (man_y + 1 < map_height && map[(man_y + 1) * map_width + man_x] == DKGRAY)
                                                                                {
                                                                                        man_y++;
                                                                                        if (man_y - screen_y > SCREEN_HEIGHT / 2 - 3)
                                                                                        {
                                                                                                screen_y += SCREEN_HEIGHT / 2;
                                                                                                if (screen_y + SCREEN_HEIGHT / 2 > map_height)
                                                                                                        screen_y = map_height - SCREEN_HEIGHT / 2;
                                                                                        }
                                                                                }
                                                                        break;
                                                        }
                                        }
                                        break;

                                case MESSAGE_KEY_UP:
                                        if (ch == CH_SPACE)
                                                man_attack = FALSE;
                                        break;
                        }
                }
dg_done:
                MessageGet(,, 1 << MESSAGE_KEY_UP);
        }
        catch
                PutExcept;
        SettingsPop;
        CleanUp;
        MenuPop;
        RegWrite("ZealOS/DunGen", "F64 best_score=%5.4f;\n", best_score);
}

DunGen;