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: 1621
- 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: 1621
- 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: 1621
- 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.