/*
Terry got tricky by not defining a color
right away in these CSprites so they can
work for both players by setting dc->color
before drawing them.  He actually made these
graphics by defining a color in the <CTRL-r>
menu, drawing the unit and deleting the color.

He had to leave a gap between the tank tread
and body because of how it is rendered when rotated.
*/

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

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

//This is an infantry.

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

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


U0 DrawHexes()
{
        F64 dx = 2 * HEX_SIDE + 2 * DCOS, dy = 2 * DSIN, x, y, x1, y1, x2, y2;
        I64 i, j;

        map_dc->color = WHITE;
        GrRect(map_dc, 0, 0, map_dc->width, map_dc->height);
        map_dc->color = BLACK;
        y = 0;
        for (j = 0; j < map_rows; j += 2)
        {
                x = DCOS;
                GrLine(map_dc, x, y, x - DCOS, y + DSIN);
                GrLine(map_dc, x - DCOS, y + DSIN, x, y + 2 * DSIN);
                for (i = 0; i < map_cols; i++)
                {
                        x1 = x;
                        y1 = y;
                        x2 = x1 + HEX_SIDE;
                        y2 = y1;
                        GrLine(map_dc, x1, y1, x2, y2);
                        x1 = x2;
                        y1 = y2;
                        x2 += DCOS;
                        y2 += DSIN;
                        GrLine(map_dc, x1, y1, x2, y2);
                        GrLine(map_dc, x2, y2, x2 - DCOS, y2 + DSIN);
                        x1 = x2;
                        y1 = y2;
                        x2 += HEX_SIDE;
                        GrLine(map_dc, x1, y1, x2, y2);
                        GrLine(map_dc, x2, y2, x2 + DCOS, y2 + DSIN);
                        x1 = x2;
                        y1 = y2;
                        x2 += DCOS;
                        y2 -= DSIN;
                        if (j || i < map_cols - 1)
                                GrLine(map_dc, x1, y1, x2, y2);
                        x += dx;
                }
                y += dy;
        }
        x = DCOS;
        for (i = 0; i < map_cols; i++)
        {
                x1 = x;
                y1 = y;
                x2 = x1 + HEX_SIDE;
                y2 = y1;
                GrLine(map_dc, x1, y1, x2, y2);
                x1 = x2;
                y1 = y2;
                x2 += DCOS;
                y2 += DSIN;
                GrLine(map_dc, x1, y1, x2, y2);
                x1 = x2;
                y1 = y2;
                x2 += HEX_SIDE;
                GrLine(map_dc, x1, y1, x2, y2);
                x1 = x2;
                y1 = y2;
                x2 += DCOS;
                y2 -= DSIN;
                GrLine(map_dc, x1, y1, x2, y2);
                x += dx;
        }
}

U0 MakeTerrain(U8 color, I64 count, I64 clus_lo, I64 clus_hi)
{
        I64 i, j, l, row, col;

        for (i = 0; i < count; i++)
        {
                col = RandU32 % map_cols;
                row = RandU32 % map_rows;
                l = clus_lo + RandU16 % (clus_hi - clus_lo + 1);
                for (j = 0; j < l; j++)
                {
                        terrain[row][col] = color;
                        Toward(&row, &col, RandU16 % 6);
                        col = ClampI64(col, 0, map_cols - 1);
                        row = ClampI64(row, 0, map_rows - 1);
                }
        }
}

U0 MakeRivers()
{
        I64 i, row, col, direction;

        for (i = 0; i < 4; i++)
        {
                row = RandU32 % map_rows;
                col = RandU32 % map_cols;
                direction = RandU16 % 6;
                while (TRUE)
                {
                        rivers[row][col] = TRUE;
                        Toward(&row, &col, direction);
                        if (!(0 <= row < map_rows && 0 <= col < map_cols))
                                break;
                        if (!(RandU16 & 3))
                                direction = (direction + (7 - RandU16 % 3)) % 6;
                }
        }
}

U0 MakeRoads()
{
        I64 i, row, col, direction;

        for (i = 0; i < 5; i++)
        {
                row = RandU32 % map_rows;
                col = RandU32 % map_cols;
                direction = RandU16 % 6;
                while (TRUE)
                {
                        roads[row][col] = TRUE;
                        Toward(&row, &col, direction);
                        if (!(0 <= row < map_rows && 0 <= col < map_cols))
                                break;
                        if (!(RandU16 % 3))
                                direction = (direction + (7 - RandU16 % 3)) % 6;
                }
        }
}

U0 DrawTerrain()
{
        I64 i, j;
        F64 x, y;

        for (j = 0; j < map_rows; j++)
                for (i = 0; i < map_cols; i++)
                {
                        map_dc->color = terrain[j][i];
                        RowCol2XY(&x, &y, j, i);
                        GrFloodFill(map_dc, x, y);
                }
}

U0 DrawRivers()
{
        I64 i, j, k, r, c;
        F64 x1, y1, x2, y2;

        for (j = 0; j < map_rows; j++)
                for (i = 0; i < map_cols; i++)
                {
                        if (rivers[j][i])
                        {
                                RowCol2XY(&x1, &y1, j, i);
                                for (k = 0; k < 6; k++)
                                {
                                        r = j;
                                        c = i;
                                        Toward(&r, &c, k);
                                        if (0 <= r < map_rows && 0 <= c < map_cols && rivers[r][c])
                                        {
                                                RowCol2XY(&x2, &y2, r, c);
                                                map_dc->color = LTBLUE;
                                                map_dc->thick = 4;
                                                GrLine3(map_dc, x1, y1, 0, x2, y2, 0);
                                                map_dc->color = BLUE;
                                                map_dc->thick = 2;
                                                GrLine3(map_dc, x1, y1, 0, x2, y2, 0);
                                        }
                                }
                        }
                }
}

U0 DrawRoads()
{
        I64 i, j, k, r, c;
        F64 x1, y1, x2, y2;

        map_dc->color = RED;
        map_dc->thick = 3;
        for (j = 0; j < map_rows; j++)
                for (i = 0; i < map_cols; i++)
                {
                        if (roads[j][i])
                        {
                                RowCol2XY(&x1, &y1, j, i);
                                for (k = 0; k < 6; k++)
                                {
                                        r = j;
                                        c = i;
                                        Toward(&r, &c, k);
                                        if (0 <= r < map_rows && 0 <= c < map_cols && roads[r][c])
                                        {
                                                RowCol2XY(&x2, &y2, r, c);
                                                GrLine3(map_dc, x1, y1, 0, x2, y2, 0);
                                        }
                                }
                        }
                }
}

U0 DrawDots()
{
        I64 i, j;
        F64 x, y;

        map_dc->color = BLACK;
        for (j = 0; j < map_rows; j++)
                for (i = 0; i < map_cols; i++)
                {
                        RowCol2XY(&x, &y, j, i);
                        GrPlot(map_dc, x, y);
                }
}

U0 HexCentersCalc()
{
        I64 i, j;
        F64 x, y;

        for (j = 0; j < map_rows; j++)
                for (i = 0; i < map_cols; i++)
                {
                        x = (2 * HEX_SIDE + 2 * DCOS) * i + HEX_SIDE / 2 + DCOS;
                        if (j & 1)
                                x += HEX_SIDE + DCOS;
                        y = DSIN * (j + 1);
                        hex_centers[j][i].x = x;
                        hex_centers[j][i].y = y;
                }
}

U0 InitMap()
{
        HexCentersCalc;
        DrawHexes;
        MemSet(terrain, PLAINS, sizeof(terrain));
        MemSet(roads, FALSE, sizeof(roads));
        MemSet(rivers, FALSE, sizeof(rivers));
        MemSet(vis_map, FALSE, sizeof(vis_map));
        MakeTerrain(MOUNTAINS, 0.03 * map_cols * map_cols, 5, 35);
        MakeTerrain(TREES, 0.03 * map_cols * map_cols, 5, 35);
        DrawTerrain;
        MakeRivers;
        DrawRivers;
        MakeRoads;
        DrawRoads;
        DrawDots;
}

U0 InitUnits()
{
        I64   i, j, row, col, type;
        Unit *tmpu;

        MemSet(units, 0, sizeof(units));
        alive_count[0] = alive_count[1]=UNITS_NUM;
        for (j = 0; j < 2; j++)
                for (i = 0; i < alive_count[j]; i++)
                {
                        tmpu = &units[j][i];
                        tmpu->player    = j;
                        tmpu->num               = i;
                        tmpu->life              = 100;
                        tmpu->facing    = RandU16 % 6;
                        if (!j)
                        {
                                if (i >= UNITS_NUM / 2)
                                {
                                        if (i >= 15 * UNITS_NUM / 16)
                                                type = UT_ARTILLERY;
                                        else
                                                type = UT_INFANTRY;
                                }
                                else
                                {
                                        if (i >= UNITS_NUM / 4)
                                                type = UT_MD_TANK;
                                        else
                                                type = UT_LT_TANK;
                                }
                        }
                        else
                        {
                                if (i >= UNITS_NUM / 2)
                                {
                                        if (i >= 15 * UNITS_NUM / 16)
                                                type = UT_ARTILLERY;
                                        else
                                                type = UT_INFANTRY;
                                }
                                else
                                {
                                        if (i >= UNITS_NUM / 4)
                                                type=UT_MD_TANK;
                                        else
                                                type=UT_LT_TANK;
                                }
                        }
                        tmpu->type=type;
                        switch (type)
                        {
                                case UT_INFANTRY:
                                        tmpu->infantry                  = TRUE;
                                        tmpu->indirect_fire             = FALSE;
                                        tmpu->armor                     = 0;
                                        tmpu->armored_attack    = 15;
                                        tmpu->unarmored_attack  = 180;
                                        tmpu->accuracy                  = 45;
                                        tmpu->range                     = 5;
                                        tmpu->movement                  = 4;
                                        tmpu->img                               = <1>;
                                        break;

                                case UT_ARTILLERY:
                                        tmpu->infantry                  = TRUE;
                                        tmpu->indirect_fire             = TRUE;
                                        tmpu->armor                     = 0;
                                        tmpu->armored_attack    = 60;
                                        tmpu->unarmored_attack  = 180;
                                        tmpu->accuracy                  = 25;
                                        tmpu->range                     = 20;
                                        tmpu->movement                  = 2;
                                        tmpu->img                               = <2>;
                                        break;

                                case UT_LT_TANK:
                                        tmpu->infantry                  = FALSE;
                                        tmpu->indirect_fire             = FALSE;
                                        tmpu->armor                     = 30;
                                        tmpu->armored_attack    = 40;
                                        tmpu->unarmored_attack  = 60;
                                        tmpu->accuracy                  = 25;
                                        tmpu->range                     = 8;
                                        tmpu->movement                  = 24;
                                        tmpu->img                               = <3>;
                                        break;

                                case UT_MD_TANK:
                                        tmpu->infantry                  = FALSE;
                                        tmpu->indirect_fire             = FALSE;
                                        tmpu->armor                     = 60;
                                        tmpu->armored_attack    = 60;
                                        tmpu->unarmored_attack  = 80;
                                        tmpu->accuracy                  = 25;
                                        tmpu->range                     = 12;
                                        tmpu->movement                  = 16;
                                        tmpu->img                               = <4>;
                                        break;
                        }
                        do
                        {
                                row = RandU32 % map_rows;
                                col = RandU32 % (map_cols / 3);
                                if (j)
                                        col += 2 * map_cols / 3;
                        }
                        while (UnitFind(row, col));

                        tmpu->row = row;
                        tmpu->col = col;
                        LBts(&tmpu->vis[cur_player], 0);
                }
}

U0 ViewPlayerSet(I8 p)
{
        CMenuEntry *tmpse;

        view_player = p;
        if (tmpse = MenuEntryFind(Fs->cur_menu, "View/Player1"))
                tmpse->checked = view_player == 0;
        if (tmpse = MenuEntryFind(Fs->cur_menu, "View/Player2"))
                tmpse->checked = view_player == 1;
}

U0 Init()
{
        DocClear;
        "GameSeed(0x%X)\n", Seed(PopUpI64Get("GameSeed(0x%X):", Seed));
        moving_unit = NULL;
        InitMap;
        ViewPlayerSet(cur_player = 0);
        enemy_player = 1;
        if (map_width < GR_WIDTH)
        {
                x0 = (MAP_WIDTH  - map_width)  >> 1;
                y0 = (MAP_HEIGHT - map_height) >> 1 + FONT_HEIGHT;
        }
        else
        {
                x0 = 0;
                y0 = FONT_HEIGHT;
        }
        InitUnits;
        QueueInit(&indirect_head);
        turn = 0;
        fire_radius = 0;
        show_vis_row = -1;
        show_vis_col = -1;
        *message_buf = 0;
        message_off_timeout = 0;
        phase = PHASE_END;
}

U0 CleanUp()
{
        QueueDel(&indirect_head, TRUE);
}

U0 PlayerPick(U8 *dirname, I64 player)
{
        I64                      i = 0;
        U8                      *st;
        CDirEntry       *tmpde, *tmpde1, *tmpde2;
        CDoc            *doc = DocNew;
        Bool            *old_silent = Silent;

        st = MStrPrint("%s/*.CC*", dirname);
        tmpde = FilesFind(st);
        Free(st);
        tmpde2 = FilesFind("~/ToTheFront/*.CC*");
        tmpde1 = tmpde;
        Silent(old_silent);

        DocPrint(doc, "Player %d Type\n\n$LTBLUE$", player + 1);
        while (tmpde1)
        {
                if (!(i++ & 3))
                        DocPrint(doc, "\n");
                st = StrNew(tmpde1->name);
                FileExtRemove(st);
                tmpde1->user_data = DocPrint(doc, "$MU-UL,\"%-10ts\",LE=%d$ ", st, tmpde1);
                Free(st);
                tmpde1 = tmpde1->next;
        }
        tmpde1 = tmpde2;
        while (tmpde1)
        {
                if (!(i++ & 3))
                        DocPrint(doc, "\n");
                st = StrNew(tmpde1->name);
                FileExtRemove(st);
                tmpde1->user_data = DocPrint(doc, "$MU-UL,\"%-10ts\",LE=%d$ ", st, tmpde1);
                Free(st);
                tmpde1 = tmpde1->next;
        }
        DocPrint(doc, "\n\n\n$FG$Create your own AI in ~/ToTheFront.");
        while ((tmpde1 = PopUpMenu(doc)) <= 0);
        ExeFile(tmpde1->full_name);
        DocDel(doc);
        DirTreeDel(tmpde);
        DirTreeDel(tmpde2);
        ExePrint("player_indirect[%d]=&PlayerIndirect;"
                         "player_move[%d]=&PlayerMove;"
                         "player_direct[%d]=&PlayerDirect;", 
                         player, player, player);
}