Complete.Org: Mailing Lists: Archives: freeciv-ai: May 2003:
[freeciv-ai] Re: findjob and manage units

[freeciv-ai] Re: findjob and manage units

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Freeciv AI development <freeciv-ai@xxxxxxxxxxx>
Subject: [freeciv-ai] Re: findjob and manage units
From: Gregory Berkolaiko <Gregory.Berkolaiko@xxxxxxxxxxxx>
Date: Sat, 3 May 2003 23:40:19 +0100 (BST)

I agree in general.

In theory, when looking for a role for a unit, we can try all roles first 
so that an assignment is found for this role and the want is calculated.  
Then the role which produced the best assignment will be taken.

In practice, however, for each unit there is an list of roles _ordered_ by 
their priorities.  So that if you can apply the unit to job A, you 
wouldn't want even to try it at the job B.  This is what Per is proposing 


On Mon, 28 Apr 2003, Per I. Mathisen wrote:

> I've been thinking on how to improve the ai_manage_units() thing.
> Currently it is a real mess, working only because we forget everything
> every turn and then recalculate all tasks, and call ai_manage_units()
> twice per turn. Since we are moving away from this scheme, we need to
> fundamentally rethink the way units are being given tasks. In particular,
> ai_manage_military() and ai_military_findjob().
> There are several goals I want to reach:
>  - We need to be able to keep an assignment over multiple turns.
>  - If a part of code relinquishes a unit assigned to it, it should be
> given other work in the same turn.
>  - We should keep trying to do something with a unit until we has
> exhausted all possible avenues for action.
>  - A unit should be able to do multiple different tasks in the same turn.
>  - A unit should be able to do the same task multiple times in the same
> turn.
>  - Some tasks should be tested for all units before other tasks. For
> example, we want manage charges before we manage their bodyguards, we want
> to give ferries a chance to reach the shore before we manage their cargo.
>  - On turn end, all units have specific roles assigned.
> (However, we can assme that once a part of the code says it cannot use a
> unit, we can assume this holds for the rest of the turn.)
> The current task distribution is very crude and done at several layers
> without much logic behind it. Air units, for example, are all snatched at
> a higher level than other military units. findjob tries to prioritize some
> tasks, but uses very crude metrics to distribute them.
> This is what I suggest instead:
> Different units roles/tasks are split up into modules - separate files -
> as far as possible. To some extent this has already begun (aiair,
> aidiplomat, settler). Each module has its own API set of
>       /* Try do something useful with punit. If ai_role is set
>        * to something other than AIUNIT_NONE then we have reserved
>        * this unit. If we completed our task, set it to AIUNIT_NONE.
>        * Return TRUE if mission successfully completed, objective
>        * reached and we can try another mission. FALSE otherwise. */
>       bool ai_*_manage(pplayer, punit)
>       /* Estimate a want for the best we could build in this city,
>          * and replace contents of *choice if our want is higher than
>          * existing want. */
>       void ai_*_choice(pplayer, pcity, choice)
> Then we have something akin to this:
>       void ai_manage_units(pplayer)
>       {
>         int role = 0;
>         /* First try to complete previous tasks. */
>         unit_list_iterate_safe(pplayer->units, punit) {
>           (void) ai_manage_unit(pplayer, punit, punit->ai.ai_role);
>         } unit_list_iterate_safe_end;
>         /* Now ensure no unit is left behind. */
>         while (role++ != AIUNIT_LAST) {
>           unit_list_iterate_safe(pplayer->units, punit) {
>             /* Call this manage func until it is exhausted */
>             if (punit->ai.ai_role == AIUNIT_NONE) {
>               while (ai_manage_unit(pplayer, punit, &role));
>             }
>           } unit_list_iterate_safe_end;
>         }
>       }
>       bool ai_manage_unit(pplayer, punit, role)
>       {
>         switch (*role) {
>           *role++; /* We have two roles so don't check twice */
>           return ai_diplomat_manage(pplayer, punit);
>         case AIUNIT_ARMY:
>           return ai_army_manage(pplayer, punit);
>         case AIUNIT_AUTO_SETTLER:
>           return ai_worker_manage(pplayer, punit);
>         case AIUNIT_BUILD_CITY:
>           return ai_settler_manage(pplayer,p unit);
>         /* etc */
>         default:
>           punit->ai.ai_role = AIUNIT_DEFEND_HOME;
>           break;
>       }
> What we want to achieve is to get useful but well-handled "recursion". It
> should be handled in one place, instead of leaving it up to each manage
> function to do it. We know from past experience (air, rampage, attack)
> that recursion is easy to get subtly wrong with un-subtle results. In this
> case, all we need to be sure of is that we only return TRUE after
> _successful and non-recursively-possible_ completion of mission (resetting
> role to AIUNIT_NONE).
> It is possible we should iterate over all roles until all units have been
> given a role instead. It is more dangerous, but the disadvantage with this
> model is that if get finished with our task, we can't try to do a
> lower-number task. This problem can be reduced by sorting the roles well,
> perhaps.
>   - Per

[Prev in Thread] Current Thread [Next in Thread]
  • [freeciv-ai] Re: findjob and manage units, Gregory Berkolaiko <=