U0 Toward(I64 *_row, I64 *_col, I64 direction)
{
        switch (direction)
        {
                case 0:
                        *_row -= 2;
                        break;

                case 1:
                        if (*_row & 1)
                                *_col += 1;
                        *_row -= 1;
                        break;

                case 2:
                        if (*_row & 1)
                                *_col += 1;
                        *_row += 1;
                        break;

                case 3:
                        *_row += 2;
                        break;

                case 4:
                        if (!(*_row & 1))
                                *_col -= 1;
                        *_row += 1;
                        break;

                case 5:
                        if (!(*_row&1))
                                *_col -= 1;
                        *_row -= 1;
                        break;
        }
}

I64 FacingChange(I64 f1, I64 f2)
{
        I64 res = (f1 + 6 - f2 ) %6;

        if (res >= 3)
                return 6 - res;
        else
                return res;
}

U0 RowCol2XY(F64 *_x, F64 *_y, I64 row, I64 col)
{
        Pt *c;

        row = ClampI64(row, 0, map_rows);
        col = ClampI64(col, 0, map_cols);
        c = &hex_centers[row][col];
        *_x = c->x;
        *_y = c->y;
}

U0 XY2RowCol(I64 *_row, I64 *_col, F64 x, F64 y)
{
        *_col = (x - DCOS / 2) / (HEX_SIDE + DCOS);
        if (*_col & 1)
                *_row = ToI64((y - DSIN) / (2 * DSIN)) * 2 + 1;
        else
                *_row = ToI64(y / (2 * DSIN)) * 2;
        *_col >>= 1;
        *_row = ClampI64(*_row, 0, map_rows - 1);
        *_col = ClampI64(*_col, 0, map_cols - 1);
}

Unit *UnitFind(I64 row, I64 col)
{//Finds unit in a hexagon.
        I64 i, j;

        for (j = 0; j < 2; j++)
                for (i = 0; i < UNITS_NUM; i++)
                        if (    units[j][i].life > 0 &&
                                        units[j][i].row == row &&
                                        units[j][i].col == col)
                                return &units[j][i];
        return NULL;
}

Bool CursorInWin(CTask *task, I64 x, I64 y)
{
        if (    0 <= x + task->scroll_x < task->pix_width &&
                        0 <= y + task->scroll_y < task->pix_height)
                return TRUE;
        else
                return FALSE;
}

U0 CursorUpdate(CTask *task, I64 x, I64 y)
{
        if (CursorInWin(task, x, y))
                XY2RowCol(&cursor_row, &cursor_col, x, y);
}

class LOSCtrl
{
        I64 r1, c1, r2, c2, distance;
};

Bool LOSPlot(LOSCtrl *l, I64 x, I64 y, I64 z)
{//We got tricky and used z as the distance from the start of the line.
        I64 row, col;

        XY2RowCol(&row, &col, x, y);
        if ((row != l->r1 || col != l->c1) &&
                (row != l->r2 || col != l->c2) &&
                terrain[row][col] != PLAINS)
        {
                if (terrain[l->r1][l->c1] == MOUNTAINS)
                {
                        if (terrain[row][col] == MOUNTAINS || z>l->distance >> 1)
                                return FALSE;
                }
                else if (terrain[l->r2][l->c2] == MOUNTAINS)
                {
                        if (terrain[row][col] == MOUNTAINS || z <= l->distance >> 1)
                                return FALSE;
                }
                else
                        return FALSE;
        }

        return TRUE;
}

Bool LOS(I64 r1, I64 c1, I64 r2, I64 c2)
{
        F64 x1, y1, x2, y2;

        LOSCtrl l;
        RowCol2XY(&x1, &y1, r1, c1);
        RowCol2XY(&x2, &y2, r2, c2);
        l.r1 = r1;
        l.c1 = c1;
        l.r2 = r2;
        l.c2 = c2;
        l.distance = Sqrt(SqrI64(x1 - x2) + SqrI64(y1 - y2));

        return Line(&l, x1, y1, 0, x2, y2, l.distance, &LOSPlot);
}