U8 movement_costs[16];
movement_costs[PLAINS]          = 2;
movement_costs[TREES]           = 6;
movement_costs[MOUNTAINS]       = 10;

I64 HexMoveOneCost(Unit *tmpu, I64 r, I64 c, I64 facing)
{
        I64 res;

        if (tmpu->infantry)
                res = 0;
        else
        {
                res = FacingChange(facing, tmpu->facing);
                if (res > 0)
                        res--;
        }
        if (roads[r][c] && roads[tmpu->row][tmpu->col])
                res += 1;
        else
        {
                if (tmpu->infantry)
                        res += 2;
                else
                {
                        res += movement_costs[terrain[r][c]];
                        if (rivers[r][c])
                                res = tmpu->movement;
                }
        }

        return res;
}

I64 HexMoveOne(I64 *_row, I64 *_col, F64 x, F64 y)
{
        I64 direction, best_direction = -1, r, c;
        F64 dd, best_dd, x1, y1;

        RowCol2XY(&x1, &y1, *_row, *_col);
        best_dd = Sqr(x1 - x) + Sqr(y1 - y);
        for (direction = 0; direction < 6; direction++)
        {
                r = *_row;
                c = *_col;
                Toward(&r, &c, direction);
                RowCol2XY(&x1, &y1, r, c);
                dd = Sqr(x1 - x) + Sqr(y1 - y);
                if (0 <= r < map_rows && 0 <= c < map_cols && dd<best_dd)
                {
                        best_dd = dd;
                        best_direction = direction;
                }
        }
        if (best_direction >= 0)
        {
                Toward(_row, _col, best_direction);
                return best_direction;
        }
        else
                return -1;
}

Bool UnitMovePlot(U0, I64 x, I64 y, I64)
{
        move_x = x;
        move_y = y;
        Sleep(5 * animation_delay);

        return TRUE;
}

U0 UnitMoveAnimation(Unit *tmpu, I64 r, I64 c, I64 facing)
{
        F64 x1, y1, x2, y2, f = facing * 60.0 * pi / 180.0;

        moving_unit = tmpu;
        RowCol2XY(&x1, &y1, tmpu->row, tmpu->col);
        move_x = x1;
        move_y = y1;
        moving = TRUE;
        if (tmpu->infantry)
                Sound(53);
        else
        {
                move_facing = tmpu->facing * 60.0 * pi / 180.0;
                Sound(41);
                while (Wrap(f - move_facing, -pi) <= 0)
                {
                        move_facing -= 0.03;
                        Sleep(5  *animation_delay);
                }
                while (Wrap(f - move_facing, -pi) > 0)
                {
                        move_facing += 0.03;
                        Sleep(5 * animation_delay);
                }
                Sound(34);
        }
        move_facing = f;
        RowCol2XY(&x2, &y2, r, c);
        Line(NULL, x1, y1, 0, x2, y2, 0, &UnitMovePlot);
        Sound;
        moving_unit = NULL;
        moving = FALSE;
}
 
Bool UnitMove(Unit *tmpu, I64 x, I64 y)
{
        Unit *target;
        I64   r, c, r0 = tmpu->row, c0=tmpu->col, i, facing;

        while (tmpu->remaining_movement > 0)
        {
                r = tmpu->row;
                c = tmpu->col;
                if ((facing = HexMoveOne(&r, &c, x, y)) < 0)
                        break;
                else
                {
                        i = HexMoveOneCost(tmpu, r, c, facing);
                        if (i > tmpu->movement)
                                i = tmpu->movement;
                        if (!tmpu->fired && tmpu->remaining_movement >= i &&
                                tmpu->remaining_movement >= tmpu->movement >> 1 &&
                                (target = UnitFind(r, c)) && target->player != tmpu->player &&
                                tmpu->infantry != target->infantry)
                        {
                                if (!HexOccupy(ToBool(target->infantry), tmpu, target))
                                {
                                        tmpu = NULL;
                                        break;
                                }
                                i = tmpu->remaining_movement;
                        }
                        if (tmpu->remaining_movement >= i && !UnitFind(r, c))
                        {
                                UnitMoveAnimation(tmpu, r, c, facing);
                                tmpu->facing=facing;
                                tmpu->remaining_movement -= i;
                                tmpu->row = r;
                                tmpu->col = c;
                                VisRecalc(VR_UPDATE_FRIENDLY_UNIT, tmpu);
                                LBEqual(&tmpu->vis[enemy_player], 0, VisRecalc(VR_ONE_ENEMY_UNIT, tmpu));
                        }
                        else
                                break;
                }
        }
        if (!tmpu || tmpu->row != r0 || tmpu->col != c0)
                return TRUE;
        else
                return FALSE;
}