I've just pushed r22135 to Steam and GoG.com -- it's primarily a hotfix update, but, it also happens to include these updates to the low-level tactical AI motion functions.harpy eagle wrote:Which revision is the change on? Just want to know when it reaches the public branch.
Determine the distance a ship can move in 1 turn
- sven
- Site Admin
- Posts: 1624
- Joined: Sat Jan 31, 2015 10:24 pm
- Location: British Columbia, Canada
- Contact:
Re: Determine the distance a ship can move in 1 turn
- harpy eagle
- Posts: 296
- Joined: Sat Mar 10, 2018 3:25 am
Re: Determine the distance a ship can move in 1 turn
Out of curiosity, is ship.s related to ship.speed_class at all?sven wrote: ship.s>4 --> turn_mult=(25/4),
ship.s==4 --> turn_mult=0.7*(25/4), and
ship.s<4--> turn_mult = (25/4)/3.
Also, what is the signature for the motion cost function? I'm guessing it's ship.motion_cost(x,y,r)?
So if I wanted to implement a function that turned a ship to face a given target, would this work?
Code: Select all
local turn_costs = {
[1] = 25/4,
[0] = 25/4*0.7,
[-1] = 25/4/3,
}
function turn_cost(ship)
return turn_costs[(ship.s > 4 and 1) or (ship.s == 4 and 0) or -1]
end
function face_target(ship, target)
local r = rotate_to_face(ship,target)
if ship.motion_cost(0,0,r) > ship.max_fuel
local sign = r/abs(r)
r = sign * ship.max_fuel/turn_cost(ship)
end
local x,y = object_center(ship)
action.move_ships{ship, x, y, r}
end
-- elsewhere...
if to_target(ship, move_target) <= attack_dist
face_target(ship, move_target)
end
Code: Select all
local x,y,r,r2 = find_min_facing_move_L2(ship,move_target,attack_dist)
if to_target(ship, move_target) <= attack_dist
x,y = object_center(ship)
end
action.move_ships{ship, x, y, r}
The second is that either way, we need to pass an x,y into action.move_ships() to actually do a turn without moving. Which is problematic because using object_center() causes all kinds of motion weirdness (ships spinning around in strange ways). In the end I just ended up using ship.x, ship.y for x,y - which mostly works but causes that wiggle I mentioned earlier.
- sven
- Site Admin
- Posts: 1624
- Joined: Sat Jan 31, 2015 10:24 pm
- Location: British Columbia, Canada
- Contact:
Re: Determine the distance a ship can move in 1 turn
Sadly, I believe ship.motion_cost doesn't actually do what you'd hope it would. However, this is a function 'ship_can_rotate' that will tell you whether or not a given rotation has a cost <= the ships current fuel.harpy eagle wrote: So if I wanted to implement a function that turned a ship to face a given target, would this work?
Equally troublesomely, the value that you'll get from rotate_to_face is an absolute rotation, i.e., a number from 0-7, that corresponds to the degree rotation x 45. So, getting the trig right requires some pain and suffering. So to do what you're trying to do, I'd probably start with a template that looked sortof like this.
Code: Select all
function face_target(ship, target)
local r = rotate_to_face(ship,target)
if not ship_can_rotate(ship,r)
for i=0,7
if ship_can_rotate(ship,i)
-- TODO figure out if this rotation is the 'best' possible approximation for r.
-- the best way i can think to do this involves using a a bunch of sin and cos calls,
-- to evaluate dot products -- and while i could write something down that *might*
-- be right, i'm not in a position to debug it atm.
end
end
end
action.move_ships{ship, ship.x, ship.y, r}
end
- sven
- Site Admin
- Posts: 1624
- Joined: Sat Jan 31, 2015 10:24 pm
- Location: British Columbia, Canada
- Contact:
Re: Determine the distance a ship can move in 1 turn
In theory, to rotate without moving, you want to send in ship.x, ship.y -- i.e., the motion command expects you to tell it where the bottom left corner of the ship's tile should be, not where it's center should be.harpy eagle wrote: The second is that either way, we need to pass an x,y into action.move_ships() to actually do a turn without moving. Which is problematic because using object_center() causes all kinds of motion weirdness (ships spinning around in strange ways). In the end I just ended up using ship.x, ship.y for x,y - which mostly works but causes that wiggle I mentioned earlier.
The weird wiggle you're seeing probably has to do with obscure behaviors of find_min_facing_move_L2 that only come into effect when the requested move is impossible. As you can see in the original version of close_and_attack r2==r is used as a flag for the situation where it's possible to move within the stated range of the target, but, not possible to rotate into a state where we're facing the target -- and, thus, where it's not worth performing the second rotation step. So, if you use r2 as a guide for a rotate_to_face_as_close_as_possible type function, you'll sometimes get nonsense.
- harpy eagle
- Posts: 296
- Joined: Sat Mar 10, 2018 3:25 am
Re: Determine the distance a ship can move in 1 turn
Ah, okay. Good to know that I was actually doing what I was supposed to be doing, after all.sven wrote:In theory, to rotate without moving, you want to send in ship.x, ship.y -- i.e., the motion command expects you to tell it where the bottom left corner of the ship's tile should be, not where it's center should be.
Who is online
Users browsing this forum: No registered users and 15 guests