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; }