[Freeciv-Dev] Re: (PR#12781) Create AI guard API
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12781 >
Here is an initial version of the API. This has not been properly
tested: I'm posting it to get feedback rather than have it committed.
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/Makefile.am freeciv.PR12781/ai/Makefile.am
--- vendor.freeciv.current/ai/Makefile.am 2005-01-24 20:43:05.000000000
+0000
+++ freeciv.PR12781/ai/Makefile.am 2005-04-13 23:54:53.000000000 +0100
@@ -25,6 +25,8 @@
aiexplorer.h \
aiferry.c \
aiferry.h \
+ aiguard.c \
+ aiguard.h \
aihand.c \
aihand.h \
aihunt.c \
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aiferry.c freeciv.PR12781/ai/aiferry.c
--- vendor.freeciv.current/ai/aiferry.c 2005-04-05 22:40:45.000000000 +0100
+++ freeciv.PR12781/ai/aiferry.c 2005-04-13 23:54:53.000000000 +0100
@@ -27,6 +27,7 @@
#include "unittools.h"
#include "aidata.h"
+#include "aiguard.h"
#include "aiexplorer.h"
#include "ailog.h"
#include "aitools.h"
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aiguard.c freeciv.PR12781/ai/aiguard.c
--- vendor.freeciv.current/ai/aiguard.c 1970-01-01 01:00:00.000000000 +0100
+++ freeciv.PR12781/ai/aiguard.c 2005-04-13 23:54:53.000000000 +0100
@@ -0,0 +1,219 @@
+/**********************************************************************
+ Freeciv - Copyright (C) 2004 - The Freeciv Project
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "log.h"
+#include "unit.h"
+
+#include "ailog.h"
+#include "aitools.h"
+
+#include "aiguard.h"
+
+
+
+/**************************************************************************
+ Do sanity checks on a guard, reporting error messages to the log
+ if necessary.
+**************************************************************************/
+void aiguard_check_guard(const struct unit *guard)
+{
+ const struct unit *charge_unit = find_unit_by_id(guard->ai.charge);
+ const struct city *charge_city = find_city_by_id(guard->ai.charge);
+ assert(BODYGUARD_NONE <= guard->ai.charge);
+ if (charge_unit && charge_unit->ai.bodyguard == BODYGUARD_WANTED
+ && charge_unit->tile != guard->tile) {
+ BODYGUARD_LOG(LOG_VERBOSE, (struct unit *)guard,
+ "guard probably en route to charge");
+ } else if (charge_unit && charge_unit->ai.bodyguard == BODYGUARD_WANTED) {
+ BODYGUARD_LOG(LOG_ERROR, (struct unit *)guard,
+ "guard unknown to co-located charge");
+ } else if (charge_unit && charge_unit->ai.bodyguard != guard->id) {
+ BODYGUARD_LOG(LOG_VERBOSE, (struct unit *)guard,
+ "inconsistent guard references");
+ } else if (!charge_unit && !charge_city && 0 < guard->ai.charge) {
+ BODYGUARD_LOG(LOG_ERROR, (struct unit *)guard,
+ "dangling guard reference");
+ }
+}
+
+/**************************************************************************
+ Do sanity checks on a charge, reporting error messages to the log
+ if necessary.
+**************************************************************************/
+void aiguard_check_charge_unit(const struct unit *charge)
+{
+ struct unit *guard = find_unit_by_id(charge->ai.bodyguard);
+ assert(BODYGUARD_WANTED <= guard->ai.bodyguard);
+ if (guard && guard->ai.charge != charge->id) {
+ UNIT_LOG(LOG_ERROR, (struct unit *)charge,
+ "inconsistent guard references");
+ }
+}
+
+/**************************************************************************
+ Remove the assignment of a charge to a guard.
+**************************************************************************/
+void aiguard_clear_charge(struct unit *guard)
+{
+ struct unit *charge_unit = find_unit_by_id(guard->ai.charge);
+ struct city *charge_city = find_city_by_id(guard->ai.charge);
+ CHECK_GUARD(guard);
+ if (charge_unit) {
+ BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "unassigned");
+ /* Our previous charge will have to look for a new body guard */
+ aiguard_request_guard(charge_unit);
+ } else if (charge_city) {
+ BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "unassigned");
+ }
+ /* else not assigned or charge was destroyed */
+ guard->ai.charge = BODYGUARD_NONE;
+}
+
+/**************************************************************************
+ Remove assignment of bodyguard for a unit.
+**************************************************************************/
+void aiguard_clear_guard(struct unit *charge)
+{
+ CHECK_CHARGE_UNIT(charge);
+ if (0 < charge->ai.bodyguard) {
+ struct unit *guard = find_unit_by_id(charge->ai.bodyguard);
+
+ if (guard && guard->ai.charge == charge->id) {
+ /* charge doesn't want us anymore */
+ guard->ai.charge = BODYGUARD_NONE;
+ }
+ }
+
+ charge->ai.bodyguard = BODYGUARD_NONE;
+}
+
+/**************************************************************************
+ Assign a bodyguard to a unit.
+**************************************************************************/
+void aiguard_assign_guard_unit(struct unit *charge, struct unit *guard)
+{
+ assert(charge);
+ assert(guard);
+ assert(guard != charge);
+ /* Usually, same_pos(charge->tile, guard->tile),
+ * but that need not be so. */
+
+ CHECK_GUARD(guard);
+ CHECK_GUARD(charge);
+ /* Remove previous assignment: */
+ aiguard_clear_charge(guard);
+ aiguard_clear_guard(charge);
+
+ ai_unit_new_role(guard, AIUNIT_ESCORT, charge->tile);
+ guard->ai.charge = charge->id;
+ charge->ai.bodyguard = guard->id;
+ BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "assigned charge");
+}
+
+/**************************************************************************
+ Assign a guard to a city.
+ Use this function rather than simply setting the unit role to
+ AIUNIT_DEFEND_HOME.
+**************************************************************************/
+void aiguard_assign_guard_city(struct city *charge, struct unit *guard)
+{
+ enum ai_unit_task task;
+ assert(charge);
+ assert(guard);
+ CHECK_GUARD(guard);
+
+ if (guard->ai.charge != charge->id) {
+ /* Remove previous assignment: */
+ aiguard_clear_charge(guard);
+ }
+
+ if (guard->tile == charge->tile && guard->homecity != charge->id
+ && guard->owner == charge->owner) {
+ /* Try to rationalise home city assignments;
+ * may fail. */
+ (void) ai_unit_make_homecity(guard, charge);
+ }
+ if (guard->homecity == charge->id) {
+ task = AIUNIT_DEFEND_HOME;
+ } else {
+ task = AIUNIT_ESCORT;
+ }
+ ai_unit_new_role(guard, task, charge->tile);
+ guard->ai.charge = charge->id;
+ BODYGUARD_LOG(LOGLEVEL_BODYGUARD, guard, "assigned charge");
+}
+
+/**************************************************************************
+ Request a (new) bodyguard for the unit.
+**************************************************************************/
+void aiguard_request_guard(struct unit *punit)
+{
+ CHECK_CHARGE_UNIT(punit);
+ /* Remove previous assignment */
+ aiguard_clear_guard(punit);
+
+ UNIT_LOG(LOGLEVEL_BODYGUARD, punit, "requests a guard");
+ punit->ai.bodyguard = BODYGUARD_WANTED;
+}
+
+/**************************************************************************
+ Has a unit requested a guard and not (yet) been provided with one?
+**************************************************************************/
+bool aiguard_wanted(struct unit *charge)
+{
+ CHECK_CHARGE_UNIT(charge);
+ return charge->ai.bodyguard == BODYGUARD_WANTED;
+}
+
+/**************************************************************************
+ Has a (guard) unit been assigned a charge?
+**************************************************************************/
+bool aiguard_has_charge(struct unit *guard)
+{
+ CHECK_GUARD(guard);
+ return guard->ai.bodyguard != BODYGUARD_NONE;
+}
+
+/**************************************************************************
+ Which unit, if any, is the body guard of a unit?
+ Returns NULL if the unit has not been assigned a guard.
+**************************************************************************/
+struct unit *aiguard_guard_of(struct unit *charge)
+{
+ CHECK_CHARGE_UNIT(charge);
+ return find_unit_by_id(charge->ai.bodyguard);
+}
+
+/**************************************************************************
+ Which unit (if any) has a guard been assigned to.
+ Returns NULL if the unit is not the guard for a unit.
+**************************************************************************/
+struct unit *aiguard_charge_unit(struct unit *guard)
+{
+ CHECK_GUARD(guard);
+ return find_unit_by_id(guard->ai.charge);
+}
+
+/**************************************************************************
+ Which city (if any) has a guard been assigned to.
+ Returns NULL if the unit is not a guard for a city.
+**************************************************************************/
+struct city *aiguard_charge_city(struct unit *guard)
+{
+ CHECK_GUARD(guard);
+ return find_city_by_id(guard->ai.charge);
+}
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aiguard.h freeciv.PR12781/ai/aiguard.h
--- vendor.freeciv.current/ai/aiguard.h 1970-01-01 01:00:00.000000000 +0100
+++ freeciv.PR12781/ai/aiguard.h 2005-04-13 23:54:53.000000000 +0100
@@ -0,0 +1,58 @@
+/**********************************************************************
+ Freeciv - Copyright (C) 2002 - The Freeciv Project
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+***********************************************************************/
+#ifndef FC__AIGUARD_H
+#define FC__AIGUARD_H
+
+#include "shared.h" /* bool type */
+
+#include "fc_types.h"
+
+#ifndef NDEBUG
+#define CHECK_GUARD(guard) aiguard_check_guard(guard)
+#define CHECK_CHARGE_UNIT(charge) aiguard_check_charge_unit(charge)
+#else
+#define CHECK_GUARD(guard) {}
+#define CHECK_CHARGE_UNIT(charge) {}
+#endif
+
+
+enum bodyguard_enum {
+ BODYGUARD_WANTED = -1,
+ BODYGUARD_NONE
+};
+
+void aiguard_check_guard(const struct unit *guard);
+
+void aiguard_check_charge_unit(const struct unit *charge);
+
+void aiguard_clear_charge(struct unit *guard);
+
+void aiguard_clear_guard(struct unit *charge);
+
+void aiguard_assign_guard_unit(struct unit *charge, struct unit *guard);
+
+void aiguard_assign_guard_city(struct city *charge, struct unit *guard);
+
+void aiguard_request_guard(struct unit *punit);
+
+bool aiguard_wanted(struct unit *charge);
+
+bool aiguard_has_charge(struct unit *charge);
+
+struct unit *aiguard_guard_of(struct unit *charge);
+
+struct unit *aiguard_charge_unit(struct unit *guard);
+
+struct city *aiguard_charge_city(struct unit *guard);
+
+#endif /* FC__AIGUARD_H */
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/ailog.c freeciv.PR12781/ai/ailog.c
--- vendor.freeciv.current/ai/ailog.c 2005-04-12 20:48:41.000000000 +0100
+++ freeciv.PR12781/ai/ailog.c 2005-04-13 23:54:53.000000000 +0100
@@ -221,7 +221,8 @@
struct unit *pcharge;
struct city *pcity;
int id = -1;
- struct tile *ptile = NULL;
+ int charge_x = -1;
+ int charge_y = -1;
const char *s = "none";
if (punit->debug) {
@@ -233,19 +234,23 @@
pcity = find_city_by_id(punit->ai.charge);
pcharge = find_unit_by_id(punit->ai.charge);
if (pcharge) {
- ptile = pcharge->tile;
+ charge_x = pcharge->tile->x;
+ charge_y = pcharge->tile->y;
id = pcharge->id;
s = unit_type(pcharge)->name;
} else if (pcity) {
- ptile = pcity->tile;
+ charge_x = pcity->tile->x;
+ charge_y = pcity->tile->y;
id = pcity->id;
s = pcity->name;
}
+ /* else perhaps the charge died */
+
my_snprintf(buffer, sizeof(buffer),
"%s's bodyguard %s[%d] (%d,%d){%s:%d@%d,%d} ",
unit_owner(punit)->name, unit_type(punit)->name,
punit->id, punit->tile->x, punit->tile->y,
- s, id, ptile->x, ptile->y);
+ s, id, charge_x, charge_y);
cat_snprintf(buffer, sizeof(buffer), msg);
if (punit->debug) {
notify_conn(game.est_connections, buffer);
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aitools.c freeciv.PR12781/ai/aitools.c
--- vendor.freeciv.current/ai/aitools.c 2005-04-12 20:48:41.000000000 +0100
+++ freeciv.PR12781/ai/aitools.c 2005-04-13 23:54:53.000000000 +0100
@@ -50,6 +50,7 @@
#include "aicity.h"
#include "aidata.h"
#include "aiferry.h"
+#include "aiguard.h"
#include "ailog.h"
#include "aitech.h"
#include "aiunit.h"
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aitools.h freeciv.PR12781/ai/aitools.h
--- vendor.freeciv.current/ai/aitools.h 2005-04-05 22:40:45.000000000 +0100
+++ freeciv.PR12781/ai/aitools.h 2005-04-13 23:54:53.000000000 +0100
@@ -40,11 +40,6 @@
#define CHECK_UNIT(punit) assert(TRUE)
#endif
-enum bodyguard_enum {
- BODYGUARD_WANTED=-1,
- BODYGUARD_NONE
-};
-
/*
* Initialise using ai_avoid_risks()
*/
diff -ruN -Xvendor.freeciv.current/diff_ignore
vendor.freeciv.current/ai/aiunit.c freeciv.PR12781/ai/aiunit.c
--- vendor.freeciv.current/ai/aiunit.c 2005-04-12 20:48:41.000000000 +0100
+++ freeciv.PR12781/ai/aiunit.c 2005-04-13 23:54:53.000000000 +0100
@@ -54,6 +54,7 @@
#include "aidiplomat.h"
#include "aiexplorer.h"
#include "aiferry.h"
+#include "aiguard.h"
#include "aihand.h"
#include "aihunt.h"
#include "ailog.h"
@@ -734,6 +735,7 @@
struct tile *ptile;
CHECK_UNIT(punit);
+ CHECK_GUARD(punit);
if (aunit && aunit->owner == punit->owner) {
/* protect a unit */
@@ -1009,6 +1011,12 @@
ai_unit_new_role(punit, AIUNIT_ESCORT, aunit->tile);
punit->ai.charge = aunit->id;
BODYGUARD_LOG(LOG_DEBUG, punit, "going to defend unit");
+ /* FIXME: There is nothing to prevent many guards choosing the same
+ * unit to defend, so swarms of potential guards can converge
+ * on a unit. */
+ /* FIXME: At some point (when we arrive at the tile of the charge?)
+ * we should set aunit->ai.bodyguard to punit->id.
+ * That seems *never* to happen, which is a bug */
}
}
TIMING_LOG(AIT_BODYGUARD, TIMER_STOP);
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API,
Benedict Adamson <=
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Per I. Mathisen, 2005/04/13
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Jason Short, 2005/04/13
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Per I. Mathisen, 2005/04/14
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Benedict Adamson, 2005/04/15
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Jason Short, 2005/04/15
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Benedict Adamson, 2005/04/15
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Benoit Hudson, 2005/04/15
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Per I. Mathisen, 2005/04/18
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Jason Short, 2005/04/18
- [Freeciv-Dev] Re: (PR#12781) Create AI guard API, Per I. Mathisen, 2005/04/18
|
|