[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stratagus-CVS] stratagus/src/ai ai_plan.c
From: |
address@hidden |
Subject: |
[Stratagus-CVS] stratagus/src/ai ai_plan.c |
Date: |
14 Dec 2003 21:46:33 +1100 |
CVSROOT: /home/strat
Module name: stratagus
Changes by: <address@hidden> 03/12/14 21:46:33
Modified files:
src/ai : ai_plan.c
Log message:
Tabs, Cleanup
Patches:
Index: stratagus/src/ai/ai_plan.c
diff -u stratagus/src/ai/ai_plan.c:1.25 stratagus/src/ai/ai_plan.c:1.26
--- stratagus/src/ai/ai_plan.c:1.25 Mon Dec 1 07:03:31 2003
+++ stratagus/src/ai/ai_plan.c Sun Dec 14 21:46:33 2003
@@ -1,16 +1,16 @@
-// _________ __ __
+// _________ __ __
// / _____// |_____________ _/ |______ ____ __ __ ______
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
-// \/ \/ \//_____/ \/
+// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
-/address@hidden ai_plan.c - AI planning functions. */
+/address@hidden ai_plan.c - AI planning functions. */
//
-// (c) Copyright 2002-2003 by Lutz Sammer and Jimmy Salmon
+// (c) Copyright 2002-2004 by Lutz Sammer and Jimmy Salmon
//
// 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
@@ -26,19 +26,18 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: ai_plan.c,v 1.25 2003/11/30 20:03:31 jsalmon3 Exp $
+// $Id: ai_plan.c,v 1.26 2003/12/14 10:46:33 wizzard Exp $
//@{
/*----------------------------------------------------------------------------
--- Includes
+-- Includes
----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "stratagus.h"
-
#include "missile.h"
#include "unittype.h"
#include "map.h"
@@ -47,688 +46,693 @@
#include "ai_local.h"
/*----------------------------------------------------------------------------
--- Variables
+-- Variables
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
--- Functions
+-- Functions
----------------------------------------------------------------------------*/
/**
-** Choose enemy on map tile.
+** Choose enemy on map tile.
**
-** @param source Unit which want to attack.
-** @param tx X position on map, tile-based.
-** @param ty Y position on map, tile-based.
+** @param source Unit which want to attack.
+** @param tx X position on map, tile-based.
+** @param ty Y position on map, tile-based.
**
-** @return Returns ideal target on map tile.
+** @return Returns ideal target on map tile.
*/
-local Unit *EnemyOnMapTile(const Unit * source, int tx, int ty)
+local Unit* EnemyOnMapTile(const Unit* source, int tx, int ty)
{
- Unit *table[UnitMax];
- Unit *unit;
- Unit *best;
- const UnitType *type;
- int n;
- int i;
-
- n = SelectUnitsOnTile(tx, ty, table);
- best = NoUnitP;
- for (i = 0; i < n; ++i) {
- unit = table[i];
- // unusable unit ?
- // if( UnitUnusable(unit) ) can't attack constructions
- // FIXME: did SelectUnitsOnTile already filter this?
- // Invisible and not Visible
- if (unit->Removed || unit->Invisible || !unit->HP
- || !(unit->Visible & (1 << source->Player->Player))
- || unit->Orders[0].Action == UnitActionDie) {
- continue;
- }
- type = unit->Type;
- if (tx < unit->X || tx >= unit->X + type->TileWidth
- || ty < unit->Y || ty >= unit->Y + type->TileHeight) {
- continue;
- }
- if (!CanTarget(source->Type, unit->Type)) {
- continue;
- }
- if (!IsEnemy(source->Player, unit)) { // a friend or neutral
- continue;
- }
- //
- // Choose the best target.
- //
- if (!best || best->Type->Priority < unit->Type->Priority) {
- best = unit;
+ Unit* table[UnitMax];
+ Unit* unit;
+ Unit* best;
+ const UnitType* type;
+ int n;
+ int i;
+
+ n = SelectUnitsOnTile(tx, ty, table);
+ best = NoUnitP;
+ for (i = 0; i < n; ++i) {
+ unit = table[i];
+ // unusable unit ?
+ // if( UnitUnusable(unit) ) can't attack constructions
+ // FIXME: did SelectUnitsOnTile already filter this?
+ // Invisible and not Visible
+ if (unit->Removed || unit->Invisible || !unit->HP
+ || !(unit->Visible & (1 << source->Player->Player))
+ || unit->Orders[0].Action == UnitActionDie) {
+ continue;
+ }
+ type = unit->Type;
+ if (tx < unit->X || tx >= unit->X + type->TileWidth
+ || ty < unit->Y || ty >= unit->Y + type->TileHeight) {
+ continue;
+ }
+ if (!CanTarget(source->Type, unit->Type)) {
+ continue;
+ }
+ if (!IsEnemy(source->Player, unit)) { // a friend or neutral
+ continue;
+ }
+ //
+ // Choose the best target.
+ //
+ if (!best || best->Type->Priority < unit->Type->Priority) {
+ best = unit;
+ }
}
- }
- return best;
+ return best;
}
/**
-** Mark all by transporter reachable water tiles.
+** Mark all by transporter reachable water tiles.
**
-** @param unit Transporter
-** @param matrix Water matrix.
+** @param unit Transporter
+** @param matrix Water matrix.
**
-** @note only works for water transporters!
+** @note only works for water transporters!
*/
local void AiMarkWaterTransporter(const Unit * unit, unsigned char *matrix)
{
- static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
- static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
- struct {
- unsigned short X;
- unsigned short Y;
- } *points;
- int size;
- int x;
- int y;
- int rx;
- int ry;
- int mask;
- int wp;
- int rp;
- int ep;
- int i;
- int w;
- unsigned char *m;
-
- x = unit->X;
- y = unit->Y;
- w = TheMap.Width + 2;
- matrix += w + w + 2;
- if (matrix[x + y * w]) { // already marked
- DebugLevel0("Done\n");
- return;
- }
-
- points = malloc(TheMap.Width * TheMap.Height);
- size = TheMap.Width * TheMap.Height / sizeof (*points);
-
- //
- // Make movement matrix.
- //
- mask = UnitMovementMask(unit);
- // Ignore all possible mobile units.
- mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);
-
- points[0].X = x;
- points[0].Y = y;
- rp = 0;
- matrix[x + y * w] = 66; // mark start point
- ep = wp = 1; // start with one point
-
- //
- // Pop a point from stack, push all neightbors which could be entered.
- //
- for (;;) {
- while (rp != ep) {
- rx = points[rp].X;
- ry = points[rp].Y;
- for (i = 0; i < 8; ++i) { // mark all neighbors
- x = rx + xoffset[i];
- y = ry + yoffset[i];
- m = matrix + x + y * w;
- if (*m) { // already checked
- continue;
- }
-
- if (CanMoveToMask(x, y, mask)) { // reachable
-
- *m = 66;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- if (++wp >= size) { // round about
- wp = 0;
- }
- /* Must be checked multiple
- } else { // unreachable
- *m=99;
- */
- }
- }
-
- if (++rp >= size) { // round about
- rp = 0;
- }
- }
-
- //
- // Continue with next frame.
+ static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
+ static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
+ struct {
+ unsigned short X;
+ unsigned short Y;
+ } *points;
+ int size;
+ int x;
+ int y;
+ int rx;
+ int ry;
+ int mask;
+ int wp;
+ int rp;
+ int ep;
+ int i;
+ int w;
+ unsigned char *m;
+
+ x = unit->X;
+ y = unit->Y;
+ w = TheMap.Width + 2;
+ matrix += w + w + 2;
+ if (matrix[x + y * w]) { // already marked
+ DebugLevel0("Done\n");
+ return;
+ }
+
+ points = malloc(TheMap.Width * TheMap.Height);
+ size = TheMap.Width * TheMap.Height / sizeof (*points);
+
+ //
+ // Make movement matrix.
+ //
+ mask = UnitMovementMask(unit);
+ // Ignore all possible mobile units.
+ mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);
+
+ points[0].X = x;
+ points[0].Y = y;
+ rp = 0;
+ matrix[x + y * w] = 66; // mark start point
+ ep = wp = 1; // start with one point
+
+ //
+ // Pop a point from stack, push all neightbors which could be entered.
//
- if (rp == wp) { // unreachable, no more points available
- break;
+ for (;;) {
+ while (rp != ep) {
+ rx = points[rp].X;
+ ry = points[rp].Y;
+ for (i = 0; i < 8; ++i) { // mark all neighbors
+ x = rx + xoffset[i];
+ y = ry + yoffset[i];
+ m = matrix + x + y * w;
+ if (*m) { // already checked
+ continue;
+ }
+
+ if (CanMoveToMask(x, y, mask)) { // reachable
+ *m = 66;
+ points[wp].X = x; // push the point
+ points[wp].Y = y;
+ if (++wp >= size) { // round about
+ wp = 0;
+ }
+ /* Must be checked multiple
+ } else { // unreachable
+ *m=99;
+ */
+ }
+ }
+
+ if (++rp >= size) { // round about
+ rp = 0;
+ }
+ }
+
+ //
+ // Continue with next frame.
+ //
+ if (rp == wp) { // unreachable, no more points available
+ break;
+ }
+ ep = wp;
}
- ep = wp;
- }
- free(points);
+ free(points);
}
/**
-** Find possible targets.
+** Find possible targets.
**
-** @param unit Attack.
-** @param matrix Water matrix.
-** @param dx Attack point X.
-** @param dy Attack point Y.
-** @param ds Attack state.
+** @param unit Attack.
+** @param matrix Water matrix.
+** @param dx Attack point X.
+** @param dy Attack point Y.
+** @param ds Attack state.
**
-** @return True if target found.
+** @return True if target found.
*/
-local int AiFindTarget(const Unit * unit, unsigned char *matrix, int *dx, int
*dy,
- int *ds)
+local int AiFindTarget(const Unit* unit, unsigned char* matrix, int* dx, int*
dy,
+ int* ds)
{
- static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
- static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
- struct {
- unsigned short X;
- unsigned short Y;
- unsigned char State;
- } *points;
- int size;
- int x;
- int y;
- int rx;
- int ry;
- int mask;
- int wp;
- int rp;
- int ep;
- int i;
- int w;
- enum { OnWater, OnLand, OnIsle } state;
- unsigned char *m;
-
- size = TheMap.Width * TheMap.Height / 2;
- points = malloc(size * sizeof (*points));
-
- x = unit->X;
- y = unit->Y;
-
- w = TheMap.Width + 2;
- mask = UnitMovementMask(unit);
- // Ignore all possible mobile units.
- mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);
-
- points[0].X = x;
- points[0].Y = y;
- points[0].State = OnLand;
- matrix += w + w + 2;
- rp = 0;
- matrix[x + y * w] = 1; // mark start point
- ep = wp = 1; // start with one point
-
- //
- // Pop a point from stack, push all neightbors which could be entered.
- //
- for (;;) {
- while (rp != ep) {
- rx = points[rp].X;
- ry = points[rp].Y;
- state = points[rp].State;
- for (i = 0; i < 8; ++i) { // mark all neighbors
- x = rx + xoffset[i];
- y = ry + yoffset[i];
- m = matrix + x + y * w;
-
- if (state != OnWater) {
- if (*m) { // already checked
- if (state == OnLand && *m == 66) { // tansporter?
- DebugLevel0Fn("->Water\n");
- *m = 6;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- points[wp].State = OnWater;
- if (++wp >= size) { // round about
- wp = 0;
- }
- }
- continue;
- }
- // Check targets on tile?
- // FIXME: the move code didn't likes a shore building as
- // target
- if (EnemyOnMapTile(unit, x, y)) {
- DebugLevel0Fn("Target found %d,%d-%d\n" _C_ x _C_ y _C_
state);
- *dx = x;
- *dy = y;
- *ds = state;
- free(points);
- return 1;
- }
-
- if (CanMoveToMask(x, y, mask)) { // reachable
-
- *m = 1;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- points[wp].State = state;
- if (++wp >= size) { // round about
- wp = 0;
- }
- } else { // unreachable
- *m = 99;
- }
- } else { // On water
- if (*m) { // already checked
- if (*m == 66) { // tansporter?
- *m = 6;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- points[wp].State = OnWater;
- if (++wp >= size) { // round about
- wp = 0;
- }
+ static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
+ static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
+ struct {
+ unsigned short X;
+ unsigned short Y;
+ unsigned char State;
+ } *points;
+ int size;
+ int x;
+ int y;
+ int rx;
+ int ry;
+ int mask;
+ int wp;
+ int rp;
+ int ep;
+ int i;
+ int w;
+ enum {
+ OnWater,
+ OnLand,
+ OnIsle
+ } state;
+ unsigned char* m;
+
+ size = TheMap.Width * TheMap.Height / 2;
+ points = malloc(size * sizeof (*points));
+
+ x = unit->X;
+ y = unit->Y;
+
+ w = TheMap.Width + 2;
+ mask = UnitMovementMask(unit);
+ // Ignore all possible mobile units.
+ mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);
+
+ points[0].X = x;
+ points[0].Y = y;
+ points[0].State = OnLand;
+ matrix += w + w + 2;
+ rp = 0;
+ matrix[x + y * w] = 1; // mark start point
+ ep = wp = 1; // start with one point
+
+ //
+ // Pop a point from stack, push all neightbors which could be entered.
+ //
+ for (;;) {
+ while (rp != ep) {
+ rx = points[rp].X;
+ ry = points[rp].Y;
+ state = points[rp].State;
+ for (i = 0; i < 8; ++i) { // mark all neighbors
+ x = rx + xoffset[i];
+ y = ry + yoffset[i];
+ m = matrix + x + y * w;
+
+ if (state != OnWater) {
+ if (*m) { // already checked
+ if (state == OnLand && *m ==
66) { // tansporter?
+
DebugLevel0Fn("->Water\n");
+ *m = 6;
+ points[wp].X = x; //
push the point
+ points[wp].Y = y;
+ points[wp].State =
OnWater;
+ if (++wp >= size) { //
round about
+ wp = 0;
+ }
+ }
+ continue;
+ }
+ // Check targets on tile?
+ // FIXME: the move code didn't likes a
shore building as
+ // target
+ if (EnemyOnMapTile(unit, x, y)) {
+ DebugLevel0Fn("Target found
%d,%d-%d\n" _C_ x _C_ y _C_ state);
+ *dx = x;
+ *dy = y;
+ *ds = state;
+ free(points);
+ return 1;
+ }
+
+ if (CanMoveToMask(x, y, mask)) { //
reachable
+
+ *m = 1;
+ points[wp].X = x; // push the
point
+ points[wp].Y = y;
+ points[wp].State = state;
+ if (++wp >= size) { // round
about
+ wp = 0;
+ }
+ } else { // unreachable
+ *m = 99;
+ }
+ } else { // On water
+ if (*m) { // already checked
+ if (*m == 66) { // tansporter?
+ *m = 6;
+ points[wp].X = x; //
push the point
+ points[wp].Y = y;
+ points[wp].State =
OnWater;
+ if (++wp >= size) { //
round about
+ wp = 0;
+ }
+ }
+ continue;
+ }
+ if (CanMoveToMask(x, y, mask)) { //
reachable
+ DebugLevel0Fn("->Land\n");
+ *m = 1;
+ points[wp].X = x; // push the
point
+ points[wp].Y = y;
+ points[wp].State = OnIsle;
+ if (++wp >= size) { // round
about
+ wp = 0;
+ }
+ } else { // unreachable
+ *m = 99;
+ }
+ }
}
- continue;
- }
- if (CanMoveToMask(x, y, mask)) { // reachable
- DebugLevel0Fn("->Land\n");
- *m = 1;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- points[wp].State = OnIsle;
- if (++wp >= size) { // round about
- wp = 0;
+
+ if (++rp >= size) { // round about
+ rp = 0;
}
- } else { // unreachable
- *m = 99;
- }
}
- }
-
- if (++rp >= size) { // round about
- rp = 0;
- }
- }
- //
- // Continue with next frame.
- //
- if (rp == wp) { // unreachable, no more points available
- break;
+ //
+ // Continue with next frame.
+ //
+ if (rp == wp) { // unreachable, no more points available
+ break;
+ }
+ ep = wp;
}
- ep = wp;
- }
- free(points);
- return 0;
+ free(points);
+ return 0;
}
/**
-** Find possible walls to target.
+** Find possible walls to target.
**
-** @param force Attack force.
+** @param force Attack force.
**
-** @return True if wall found.
+** @return True if wall found.
*/
-global int AiFindWall(AiForce * force)
+global int AiFindWall(AiForce* force)
{
- static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
- static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
- struct {
- unsigned short X;
- unsigned short Y;
- } *points;
- int size;
- int x;
- int y;
- int rx;
- int ry;
- int mask;
- int wp;
- int rp;
- int ep;
- int i;
- int w;
- unsigned char *m;
- unsigned char *matrix;
- int destx;
- int desty;
- AiUnit *aiunit;
- Unit *unit;
-
- // Find a unit to use. Best choice is a land unit with range 1.
- // Next best choice is any land unit. Otherwise just use the first.
- aiunit = force->Units;
- unit = aiunit->Unit;
- while (aiunit) {
- if (aiunit->Unit->Type->UnitType == UnitTypeLand) {
- unit = aiunit->Unit;
- if (aiunit->Unit->Type->Missile.Missile->Range == 1) {
- break;
- }
- }
- aiunit = aiunit->Next;
- }
-
- x = unit->X;
- y = unit->Y;
- size = TheMap.Width * TheMap.Height / 4;
- points = malloc(size * sizeof (*points));
-
- destx = -1;
- desty = -1;
-
- matrix = CreateMatrix();
- w = TheMap.Width + 2;
- matrix += w + w + 2;
-
- points[0].X = x;
- points[0].Y = y;
- rp = 0;
- matrix[x + y * w] = 1; // mark start point
- ep = wp = 1; // start with one point
-
- mask = UnitMovementMask(unit);
-
- //
- // Pop a point from stack, push all neighbors which could be entered.
- //
- for (; destx == -1;) {
- while (rp != ep && destx == -1) {
- rx = points[rp].X;
- ry = points[rp].Y;
- for (i = 0; i < 8; ++i) { // mark all neighbors
- x = rx + xoffset[i];
- y = ry + yoffset[i];
- m = matrix + x + y * w;
- if (*m) {
- continue;
- }
- //
- // Check for a wall
- //
- if (WallOnMap(x, y)) {
- DebugLevel0Fn("Wall found %d,%d\n" _C_ x _C_ y);
- destx = x;
- desty = y;
- break;
- }
+ static const int xoffset[] = { 0, -1, +1, 0, -1, +1, -1, +1 };
+ static const int yoffset[] = { -1, 0, 0, +1, -1, -1, +1, +1 };
+ struct {
+ unsigned short X;
+ unsigned short Y;
+ } *points;
+ int size;
+ int x;
+ int y;
+ int rx;
+ int ry;
+ int mask;
+ int wp;
+ int rp;
+ int ep;
+ int i;
+ int w;
+ unsigned char *m;
+ unsigned char *matrix;
+ int destx;
+ int desty;
+ AiUnit *aiunit;
+ Unit *unit;
- if (CanMoveToMask(x, y, mask)) { // reachable
- *m = 1;
- points[wp].X = x; // push the point
- points[wp].Y = y;
- if (++wp >= size) { // round about
- wp = 0;
- }
- } else { // unreachable
- *m = 99;
+ // Find a unit to use. Best choice is a land unit with range 1.
+ // Next best choice is any land unit. Otherwise just use the first.
+ aiunit = force->Units;
+ unit = aiunit->Unit;
+ while (aiunit) {
+ if (aiunit->Unit->Type->UnitType == UnitTypeLand) {
+ unit = aiunit->Unit;
+ if (aiunit->Unit->Type->Missile.Missile->Range == 1) {
+ break;
+ }
}
- }
- if (++rp >= size) { // round about
- rp = 0;
- }
+ aiunit = aiunit->Next;
}
+ x = unit->X;
+ y = unit->Y;
+ size = TheMap.Width * TheMap.Height / 4;
+ points = malloc(size * sizeof (*points));
+
+ destx = -1;
+ desty = -1;
+
+ matrix = CreateMatrix();
+ w = TheMap.Width + 2;
+ matrix += w + w + 2;
+
+ points[0].X = x;
+ points[0].Y = y;
+ rp = 0;
+ matrix[x + y * w] = 1; // mark start point
+ ep = wp = 1; // start with one point
+
+ mask = UnitMovementMask(unit);
+
//
- // Continue with next frame.
+ // Pop a point from stack, push all neighbors which could be entered.
//
- if (rp == wp) { // unreachable, no more points available
- break;
+ for (; destx == -1;) {
+ while (rp != ep && destx == -1) {
+ rx = points[rp].X;
+ ry = points[rp].Y;
+ for (i = 0; i < 8; ++i) { // mark all neighbors
+ x = rx + xoffset[i];
+ y = ry + yoffset[i];
+ m = matrix + x + y * w;
+ if (*m) {
+ continue;
+ }
+ //
+ // Check for a wall
+ //
+ if (WallOnMap(x, y)) {
+ DebugLevel0Fn("Wall found %d,%d\n" _C_
x _C_ y);
+ destx = x;
+ desty = y;
+ break;
+ }
+
+ if (CanMoveToMask(x, y, mask)) { // reachable
+ *m = 1;
+ points[wp].X = x; // push the point
+ points[wp].Y = y;
+ if (++wp >= size) { // round about
+ wp = 0;
+ }
+ } else { // unreachable
+ *m = 99;
+ }
+ }
+ if (++rp >= size) { // round about
+ rp = 0;
+ }
+ }
+
+ //
+ // Continue with next frame.
+ //
+ if (rp == wp) { // unreachable, no more points available
+ break;
+ }
+ ep = wp;
}
- ep = wp;
- }
- free(points);
+ free(points);
- if (destx != -1) {
- force->State = 0;
- aiunit = force->Units;
- while (aiunit) {
- if (aiunit->Unit->Type->CanAttack) {
- CommandAttack(aiunit->Unit, destx, desty, NULL, FlushCommands);
- } else {
- CommandMove(aiunit->Unit, destx, desty, FlushCommands);
- }
- aiunit = aiunit->Next;
+ if (destx != -1) {
+ force->State = 0;
+ aiunit = force->Units;
+ while (aiunit) {
+ if (aiunit->Unit->Type->CanAttack) {
+ CommandAttack(aiunit->Unit, destx, desty, NULL,
FlushCommands);
+ } else {
+ CommandMove(aiunit->Unit, destx, desty,
FlushCommands);
+ }
+ aiunit = aiunit->Next;
+ }
+ return 1;
}
- return 1;
- }
- return 0;
+ return 0;
}
/**
-** Plan an attack with a force.
-** We know, that we must use a transporter.
+** Plan an attack with a force.
+** We know, that we must use a transporter.
**
-** @param force Pointer on the force.
+** @param force Pointer on the force.
**
-** @return True if target found, false otherwise.
+** @return True if target found, false otherwise.
**
-** @todo Perfect planning.
-** Only works for water transporter!
+** @todo Perfect planning.
+** Only works for water transporter!
*/
-global int AiPlanAttack(AiForce * force)
+global int AiPlanAttack(AiForce* force)
{
- char *watermatrix;
- const AiUnit *aiunit;
- int x;
- int y;
- int i;
- int state;
- Unit *transporter;
-
- DebugLevel0Fn("Planning for force #%d of player #%d\n"
- _C_ force - AiPlayer->Force _C_ AiPlayer->Player->Player);
-
- watermatrix = CreateMatrix();
-
- //
- // Transporter must be already assigned to the force.
- // NOTE: finding free transportes was too much work for me.
- //
- aiunit = force->Units;
- state = 1;
- while (aiunit) {
- if (aiunit->Unit->Type->Transporter) {
- DebugLevel0Fn("Transporter #%d\n" _C_ UnitNumber(aiunit->Unit));
- AiMarkWaterTransporter(aiunit->Unit, watermatrix);
- state = 0;
- }
- aiunit = aiunit->Next;
- }
-
- //
- // No transport that belongs to the force.
- //
- transporter = NULL;
- if (state) {
- for (i = 0; i < AiPlayer->Player->TotalNumUnits; ++i) {
- Unit *unit;
-
- unit = AiPlayer->Player->Units[i];
- if (unit->Type->Transporter && UnitIdle(unit)) {
- DebugLevel0Fn("Assign any transporter\n");
- AiMarkWaterTransporter(unit, watermatrix);
- // FIXME: can be the wrong transporter.
- transporter = unit;
- state = 0;
- }
- }
- }
-
- if (state) { // Absolute no transporter
- DebugLevel0Fn("No transporter available\n");
- // FIXME: should tell the resource manager we need a transporter!
- return 0;
- }
- //
- // Find a land unit of the force.
- // FIXME: if force is split over different places -> broken
- //
- aiunit = force->Units;
- while (aiunit) {
- if (aiunit->Unit->Type->UnitType == UnitTypeLand) {
- DebugLevel0Fn("Landunit %d\n" _C_ UnitNumber(aiunit->Unit));
- break;
+ char* watermatrix;
+ const AiUnit* aiunit;
+ int x;
+ int y;
+ int i;
+ int state;
+ Unit* transporter;
+
+ DebugLevel0Fn("Planning for force #%d of player #%d\n"
+ _C_ force - AiPlayer->Force _C_ AiPlayer->Player->Player);
+
+ watermatrix = CreateMatrix();
+
+ //
+ // Transporter must be already assigned to the force.
+ // NOTE: finding free transportes was too much work for me.
+ //
+ aiunit = force->Units;
+ state = 1;
+ while (aiunit) {
+ if (aiunit->Unit->Type->Transporter) {
+ DebugLevel0Fn("Transporter #%d\n" _C_
UnitNumber(aiunit->Unit));
+ AiMarkWaterTransporter(aiunit->Unit, watermatrix);
+ state = 0;
+ }
+ aiunit = aiunit->Next;
}
- aiunit = aiunit->Next;
- }
- if (!aiunit) {
- DebugLevel0Fn("No land unit in force\n");
- return 0;
- }
+ //
+ // No transport that belongs to the force.
+ //
+ transporter = NULL;
+ if (state) {
+ for (i = 0; i < AiPlayer->Player->TotalNumUnits; ++i) {
+ Unit *unit;
+
+ unit = AiPlayer->Player->Units[i];
+ if (unit->Type->Transporter && UnitIdle(unit)) {
+ DebugLevel0Fn("Assign any transporter\n");
+ AiMarkWaterTransporter(unit, watermatrix);
+ // FIXME: can be the wrong transporter.
+ transporter = unit;
+ state = 0;
+ }
+ }
+ }
- if (AiFindTarget(aiunit->Unit, watermatrix, &x, &y, &state)) {
- AiUnit *aiunit;
+ if (state) { // Absolute no transporter
+ DebugLevel0Fn("No transporter available\n");
+ // FIXME: should tell the resource manager we need a
transporter!
+ return 0;
+ }
+ //
+ // Find a land unit of the force.
+ // FIXME: if force is split over different places -> broken
+ //
+ aiunit = force->Units;
+ while (aiunit) {
+ if (aiunit->Unit->Type->UnitType == UnitTypeLand) {
+ DebugLevel0Fn("Landunit %d\n" _C_
UnitNumber(aiunit->Unit));
+ break;
+ }
+ aiunit = aiunit->Next;
+ }
- if (transporter) {
- aiunit = malloc(sizeof (*aiunit));
- aiunit->Next = force->Units;
- force->Units = aiunit;
- aiunit->Unit = transporter;
- RefsIncrease(transporter);
- }
-
- DebugLevel0Fn("Can attack\n");
- force->GoalX = x;
- force->GoalY = y;
- force->MustTransport = state == 2;
-
- force->State = 1;
- return 1;
- }
- return 0;
+ if (!aiunit) {
+ DebugLevel0Fn("No land unit in force\n");
+ return 0;
+ }
+
+ if (AiFindTarget(aiunit->Unit, watermatrix, &x, &y, &state)) {
+ AiUnit *aiunit;
+
+ if (transporter) {
+ aiunit = malloc(sizeof (*aiunit));
+ aiunit->Next = force->Units;
+ force->Units = aiunit;
+ aiunit->Unit = transporter;
+ RefsIncrease(transporter);
+ }
+
+ DebugLevel0Fn("Can attack\n");
+ force->GoalX = x;
+ force->GoalY = y;
+ force->MustTransport = state == 2;
+
+ force->State = 1;
+ return 1;
+ }
+ return 0;
}
/**
-** Respond to ExplorationRequests
+** Respond to ExplorationRequests
*/
void AiSendExplorers(void)
{
- AiExplorationRequest* request;
- int requestcount;
- int requestid;
- int centerx,centery;
- int x,y;
- int i;
- int targetok;
- int ray;
- int trycount;
- int outtrycount;
-
- Unit** unit;
- UnitType * type;
- Unit* bestunit;
- int distance;
- int bestdistance;
- int flyeronly;
-
- // Count requests...
- request = AiPlayer->FirstExplorationRequest;
- requestcount = 0;
-
- while (request) {
- requestcount ++;
-
- request = request->Next;
- }
-
- // Nothing => abort
- if (!requestcount) {
- return;
- }
-
- outtrycount = 0;
- do {
- bestunit = 0;
- outtrycount++;
-
- // Choose a request
- requestid = SyncRand() % requestcount;
+ AiExplorationRequest* request;
+ int requestcount;
+ int requestid;
+ int centerx;
+ int centery;
+ int x;
+ int y;
+ int i;
+ int targetok;
+ int ray;
+ int trycount;
+ int outtrycount;
+
+ Unit** unit;
+ UnitType* type;
+ Unit* bestunit;
+ int distance;
+ int bestdistance;
+ int flyeronly;
+ // Count requests...
request = AiPlayer->FirstExplorationRequest;
- while (requestid) {
- request = request->Next;
- requestid--;
- }
- // Choose a target, "near"
- centerx = request->X;
- centery = request->Y;
- ray = 3;
- trycount = 0;
+ requestcount = 0;
+
+ while (request) {
+ requestcount ++;
+ request = request->Next;
+ }
+
+ // Nothing => abort
+ if (!requestcount) {
+ return;
+ }
+
+ outtrycount = 0;
do {
- targetok = 0;
+ bestunit = 0;
+ outtrycount++;
+
+ // Choose a request
+ requestid = SyncRand() % requestcount;
+
+ request = AiPlayer->FirstExplorationRequest;
+ while (requestid) {
+ request = request->Next;
+ requestid--;
+ }
+ // Choose a target, "near"
+ centerx = request->X;
+ centery = request->Y;
+ ray = 3;
+ trycount = 0;
+
+ do {
+ targetok = 0;
+
+ x = centerx + SyncRand() % (2 * ray + 1) - ray;
+ y = centery + SyncRand() % (2 * ray + 1) - ray;
+
+ if (x >= 0 && y >= 0 && x < TheMap.Width && y <
TheMap.Height) {
+ targetok =
!IsMapFieldExplored(AiPlayer->Player, x, y);
+ }
+
+ ray = 3 * ray / 2;
+ trycount ++;
+ } while (trycount < 8 && !targetok);
+
+ if (!targetok) {
+ continue;
+ }
- x = centerx + SyncRand() % (2 * ray + 1) - ray;
- y = centery + SyncRand() % (2 * ray + 1) - ray;
+ // We have an unexplored tile in sight (x,y)
- if (x >= 0 && y >= 0 && x < TheMap.Width && y < TheMap.Height) {
- targetok = !IsMapFieldExplored(AiPlayer->Player, x, y);
- }
-
- ray = 3 * ray / 2;
- trycount ++;
- } while (trycount < 8 && !targetok);
-
- if (!targetok) {
- continue;
- }
-
- // We have an unexplored tile in sight (x,y)
-
- // Find an idle unit, responding to the mask
- flyeronly = 0;
- bestdistance = -1;
-
- unit = AiPlayer->Player->Units;
- for (i = AiPlayer->Player->TotalNumUnits; i > 0; unit++) {
- i--;
-
- if (!UnitIdle((*unit))) {
- continue;
- }
-
- if ((*unit)->X == -1 || (*unit)->Y == -1) {
- continue;
- }
-
- type = (*unit)->Type;
-
- if (type->Building) {
- continue;
- }
-
- if (type->UnitType != UnitTypeFly) {
- if (flyeronly) {
- continue;
- }
- if ((request->Mask & MapFieldLandUnit) && (type->UnitType !=
UnitTypeLand)) {
- continue;
- }
- if ((request->Mask & MapFieldSeaUnit) && (type->UnitType !=
UnitTypeNaval)) {
- continue;
- }
- } else {
- flyeronly = 1;
- }
-
- distance = ((*unit)->X - x) * ((*unit)->X - x) + ((*unit)->Y - y) *
((*unit)->Y - y);
- if (bestdistance == -1 || distance <= bestdistance ||
- (bestunit->Type->UnitType != UnitTypeFly && type->UnitType
== UnitTypeFly)) {
- bestdistance = distance;
- bestunit = (*unit);
- }
- }
- } while(outtrycount <= 4 && !bestunit);
-
- if (bestunit) {
- CommandMove(bestunit, x, y, FlushCommands);
- AiPlayer->LastExplorationGameCycle=GameCycle;
- }
-
- // Remove all requests
- while (AiPlayer->FirstExplorationRequest) {
- request = AiPlayer->FirstExplorationRequest->Next;
- free(AiPlayer->FirstExplorationRequest);
- AiPlayer->FirstExplorationRequest = request;
- }
+ // Find an idle unit, responding to the mask
+ flyeronly = 0;
+ bestdistance = -1;
+
+ unit = AiPlayer->Player->Units;
+ for (i = AiPlayer->Player->TotalNumUnits; i > 0; ++unit) {
+ --i;
+
+ if (!UnitIdle((*unit))) {
+ continue;
+ }
+
+ if ((*unit)->X == -1 || (*unit)->Y == -1) {
+ continue;
+ }
+
+ type = (*unit)->Type;
+
+ if (type->Building) {
+ continue;
+ }
+
+ if (type->UnitType != UnitTypeFly) {
+ if (flyeronly) {
+ continue;
+ }
+ if ((request->Mask & MapFieldLandUnit) &&
(type->UnitType != UnitTypeLand)) {
+ continue;
+ }
+ if ((request->Mask & MapFieldSeaUnit) &&
(type->UnitType != UnitTypeNaval)) {
+ continue;
+ }
+ } else {
+ flyeronly = 1;
+ }
+
+ distance = ((*unit)->X - x) * ((*unit)->X - x) +
((*unit)->Y - y) * ((*unit)->Y - y);
+ if (bestdistance == -1 || distance <= bestdistance ||
+ (bestunit->Type->UnitType !=
UnitTypeFly && type->UnitType == UnitTypeFly)) {
+ bestdistance = distance;
+ bestunit = (*unit);
+ }
+ }
+ } while(outtrycount <= 4 && !bestunit);
+
+ if (bestunit) {
+ CommandMove(bestunit, x, y, FlushCommands);
+ AiPlayer->LastExplorationGameCycle=GameCycle;
+ }
+
+ // Remove all requests
+ while (AiPlayer->FirstExplorationRequest) {
+ request = AiPlayer->FirstExplorationRequest->Next;
+ free(AiPlayer->FirstExplorationRequest);
+ AiPlayer->FirstExplorationRequest = request;
+ }
}
//@}
- [Stratagus-CVS] stratagus/src/ai ai_plan.c,
address@hidden <=