[freeciv-ai] ferrying (long)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
I've been looking at the ferrying code in the AI, and I cannot but
despair. What _is_ this??
As far as I can see, ai_military_gothere() tries to acquire a boat from a
city it can goto, and the nearer the better. Then it tries to go there and
jump aboard with lots of code that seems to do very little actually. A
boat will never go to the passenger, even though the boat has much more
movement. The result is that the AI will build a lot of boats to
Further, ai_military_gothere() moves the boat onward and tries to drop off
the passengers. More often than not, it will fail, since it may take
several turns to arrive. It will then try again and again several times
per turn through the ai_military_attack() loop, since it mistakenly
believes that the passenger is capable of doing anything while stuck on
Now, enter ai_manage_ferryboat(). It also seems to move the ferry. There
does not seem to be a reason for this duplication. It does not drop off
passengers, though. They have to wait until next time they are activated
in the management loop, which could be at the end of the currently started
turn or at the beginning of next (ie possibly very bad).
Each ferry can only have two passengers. One real passenger, and one
bodyguard. Occasionally it takes more, however, and how it does this is a
mystery of hedgemagic code that probably not even Syela knew how worked.
Add to this that ai_military_gothere() will attempt to use a ferry
whenever a ferry is possible, instead of going a much shorter route by
I don't see any way to salvage this code. It is just so unbelievably bad.
Let's instead discuss how to create an alternative ferry system.
Here is a suggestion:
A unit has an int unit->ai.ferryboat, which is FERRY_NONE, FERRY_WANTED,
or an int > 0 which corresponds to a ferry's unit->id. If an AI unit is
SENTRY, it is waiting for a ferry and its unit->ai.ferryboat may not be
FERRY_NONE, its unit->goto_dest_* contains its desired destination, and
its unit->ai.ai_role contains its role at destination.
A ferry which is IDLE is ready for getting a new assignment. A ferry which
is GOTO is busy. While GOTO it should head towards the goto destination.
If arrived && is empty of passengers, attempt to pick up any unit that
have (unit->ai.ferryboat == ferry's unit->id), and set its goto_dest_* to
the units' goto_dest_*. We assume all units with our id as tickets have
the same destination. If arrived && has passengers, drop them off.
(If we spent all our movement but did not arrive and there are passengers
with our id as tickets somewhere (ie waiting for us), try to move them
towards us as much as we can, possibly jumping aboard. But this is hard to
do, I think, since we can only have one warmap at a time.)
When acquiring a new mission (having found new passengers), we check if
these passengers are military. If they are, we set our unit->ai.bodyguard
to BODYGUARD_WANTED. A ferry will only have BODYGUARD_WANTED when going to
pick up passengers, if we don't have a bodyguard by then, set it to
BODYGUARD_NONE (not realistic that any can catch up in time). When we have
arrived, before dropping off our passengers, release the bodyguard and
call ai_military_attack(bodyguard) for some first whacking of the target.
In ai_military_bodyguard() we special case the bodyguarding of ferries, so
that instead of going to the ferry's position to meet it, we go to its
pick up destination instead. That way we get a much greater than chance of
actually meeting. We also allow for slower ships to bodyguard a ferry
(battleships are nice for prewhacking a city).
Units that want to be ferried somewhere should go to a coastal tile. When
attempting to find a ferry, units should iterate through all IDLE ferries
and find the closest. If one is found, set unit->ai.ferryboat to its id
and go SENTRY. If not, set unit->ai.ferryboat to FERRY_WANTED and go
In military advisor, check if any units are waiting for a ferry. If there
are, and the number of units waiting for a ferry is larger than the number
of busy ferries divided by two, then buy more with very high want.
This system should work, but it is not optimal. For an optimal system, we
- dual warmaps for determining best meeting point between ferry and
- a way to figure out if one ferry can carry several payloads of
passengers from 1+ pick up points to 1+ targets (for example two
settlers to two different city spots on the same continent)
But I don't see an easy way to actually implementing those at the moment.
Comments / ideas?
"I don't see why people are so upset about cloning sheep. American
television networks have been doing that to their audiences for years."
-- Jello Biafra
|[Prev in Thread]
||[Next in Thread]|
- [freeciv-ai] ferrying (long),
Per I. Mathisen <=