AI uses the transporters better, code cleanups.

This commit is contained in:
johns 2002-03-19 22:44:00 +00:00
parent 750654a3a6
commit 65b9398100
4 changed files with 164 additions and 66 deletions

View file

@ -356,10 +356,19 @@ global void AiAttackWithForce(int force)
} }
} }
//----------------------------------------------------------------------------
// Handle attack of force with transporter.
//----------------------------------------------------------------------------
/** /**
** Step 1)
** Load force on transporters. ** Load force on transporters.
** **
** @param force Force pointer. ** @param force Force pointer.
**
** @todo If an unit can't reach the transporter the code hangs.
** We must the transporter land on a new position.
** Or the board action will be better written.
*/ */
local void AiLoadForce(AiForce* force) local void AiLoadForce(AiForce* force)
{ {
@ -427,9 +436,14 @@ local void AiLoadForce(AiForce* force)
} }
/** /**
** Send force off transporters. ** Step 2)
** Send force awaay in transporters, to unload at target position.
** **
** @param force Force pointer. ** @param force Force pointer.
**
** @todo The transporter should avoid enemy contact and should land
** at an unfortified coast. If we send more transporters they
** should land on different positions.
*/ */
local void AiSendTransporter(AiForce* force) local void AiSendTransporter(AiForce* force)
{ {
@ -440,8 +454,13 @@ local void AiSendTransporter(AiForce* force)
// //
aiunit=force->Units; aiunit=force->Units;
while( aiunit ) { while( aiunit ) {
// Transporter to unload units
if( aiunit->Unit->Type->Transporter ) { if( aiunit->Unit->Type->Transporter ) {
CommandMove(aiunit->Unit, force->GoalX, force->GoalY, CommandUnload(aiunit->Unit, force->GoalX, force->GoalY, NoUnitP,
FlushCommands);
// Ships to defend transporter
} else if( aiunit->Unit->Type->UnitType==UnitTypeNaval ) {
CommandAttack(aiunit->Unit, force->GoalX, force->GoalY, NoUnitP,
FlushCommands); FlushCommands);
} }
aiunit=aiunit->Next; aiunit=aiunit->Next;
@ -450,14 +469,19 @@ local void AiSendTransporter(AiForce* force)
} }
/** /**
** Step 3)
** Wait for transporters landed. ** Wait for transporters landed.
** **
** @param force Force pointer. ** @param force Force pointer.
**
** @todo If units blocks the unload process we should move them away.
** FIXME: hangs if the unit can't unloaded.
*/ */
local void AiWaitLanded(AiForce* force) local void AiWaitLanded(AiForce* force)
{ {
AiUnit* aiunit; AiUnit* aiunit;
int i; int i;
int j;
DebugLevel0Fn("Waiting\n"); DebugLevel0Fn("Waiting\n");
// //
@ -466,13 +490,20 @@ local void AiWaitLanded(AiForce* force)
i=1; i=1;
aiunit=force->Units; aiunit=force->Units;
while( aiunit ) { while( aiunit ) {
if( aiunit->Unit->Type->Transporter if( aiunit->Unit->Type->Transporter ) {
&& aiunit->Unit->Orders[0].Action==UnitActionStill ) { if( aiunit->Unit->Orders[0].Action==UnitActionStill ) {
DebugLevel0Fn("Unloading\n"); DebugLevel0Fn("Unloading\n");
CommandUnload(aiunit->Unit,aiunit->Unit->X,aiunit->Unit->Y, for( j=0; j<MAX_UNITS_ONBOARD; ++j ) {
NoUnitP,FlushCommands); if( aiunit->Unit->OnBoard[j] ) {
} else { CommandUnload(aiunit->Unit,force->GoalX,force->GoalY,
i=0; NoUnitP,FlushCommands);
i=0;
break;
}
}
} else {
i=0;
}
} }
aiunit=aiunit->Next; aiunit=aiunit->Next;
} }
@ -482,7 +513,8 @@ local void AiWaitLanded(AiForce* force)
} }
/** /**
** Force on attack ride. ** Step 4)
** Force on attack ride. We attack until there is no unit or enemy left.
** **
** @param force Force pointer. ** @param force Force pointer.
*/ */

View file

@ -93,69 +93,96 @@ local void AiInitMagic(void)
} }
/** /**
** Do magic for ogre-mage. ** Check if the unit should cast the "bloodlust" spell.
**
** If the spell is available and the unit has enough mana, the surrounding
** of the unit is checked if any enemy units are in sight. If enemy units
** are in sight the spell is casted on own units in range.
**
** @param unit Magic unit.
**
** @return True, if a spell is casted.
**
** @note This function can also be used for auto bloodlust.
*/ */
local void AiDoOgreMage(Unit* unit) local int AiBloodlustSpell(Unit* unit)
{ {
Unit* best;
Unit* table[UnitMax];
int r; int r;
int i;
int n;
if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-bloodlust") ) { if (UpgradeIdentAvailable(AiPlayer->Player, "upgrade-bloodlust")
if( unit->Mana>AiBloodlust->ManaCost ) { && unit->Mana > AiBloodlust->ManaCost) {
Unit* table[UnitMax];
int n;
int i;
r=unit->Type->ReactRangeComputer; r = unit->Type->ReactRangeComputer;
n=SelectUnits(unit->X-r,unit->Y-r,unit->X+r+1,unit->Y+r+1,table); n = SelectUnits(unit->X - r, unit->Y - r, unit->X + r + 1,
if( n ) { unit->Y + r + 1, table);
for( i=0; i<n; ++i ) {
Unit* best;
// a friend or neutral for (i = 0; i < n; ++i) {
if( !IsEnemy(unit->Player,table[i]) ) {
continue; // an enemy which can attack
} if (!IsEnemy(unit->Player, table[i])
if( !table[i]->Type->CanAttack ) { || (!table[i]->Type->CanAttack)) {
continue; continue;
} }
// //
// We have an enemy in range. // We have an enemy in range.
// //
best=NoUnitP; best = NoUnitP;
for( i=0; i<n; ++i ) { for (i = 0; i < n; ++i) {
if( table[i]==unit // not self, not already bloodlust and can attack
|| table[i]->Bloodlust if (table[i] == unit || table[i]->Bloodlust
|| !table[i]->Type->CanAttack ) { || !table[i]->Type->CanAttack) {
continue; continue;
} }
// Allied unit // Allied unit
// FIXME: should ally to self // FIXME: should ally to self
if( unit->Player!=table[i]->Player && if (unit->Player != table[i]->Player
!IsAllied(unit->Player,table[i]) ) { && !IsAllied(unit->Player, table[i])) {
continue; continue;
} }
r=MapDistanceBetweenUnits(unit,table[i]); r = MapDistanceBetweenUnits(unit, table[i]);
DebugLevel0Fn("Distance %d\n",r); DebugLevel0Fn("Distance %d\n", r);
if( r<=1 ) { if (r <= 1) {
DebugLevel0Fn("`%s' cast bloodlust\n" DebugLevel0Fn("`%s' cast bloodlust\n" _C_ unit->Type->
_C_ unit->Type->Ident); Ident);
CommandSpellCast(unit,0,0,table[i], CommandSpellCast(unit, 0, 0, table[i], AiBloodlust,
AiBloodlust,FlushCommands); FlushCommands);
break; return 1;
} }
if( r==2 ) { if (r == 2) {
best=table[i]; best = table[i];
}
}
if( best ) {
CommandSpellCast(unit,0,0,best,
AiBloodlust,FlushCommands);
}
break;
} }
} }
if (best) {
CommandSpellCast(unit, 0, 0, best, AiBloodlust,
FlushCommands);
return 1;
}
break;
} }
} }
return 0;
}
/**
** Check if the unit should cast the "eye of vision" spell.
**
** If the unit has nothing to do and the spell is available and the unit
** has full mana cast with a change of 1/32 the spell. The spells does
** nothing, because the AI cheats and already knows the surroundings.
**
** @param unit Magic unit.
**
** @return True, if a spell is casted.
**
** @note This function can also be used for auto eye of vision.
*/
local int AiEyeOfVisionSpell(Unit* unit)
{
int r;
if( unit->Orders[0].Action==UnitActionStill ) { if( unit->Orders[0].Action==UnitActionStill ) {
if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-eye-of-kilrogg") if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-eye-of-kilrogg")
@ -169,16 +196,41 @@ local void AiDoOgreMage(Unit* unit)
CommandSpellCast(unit,unit->X,unit->Y,NoUnitP, CommandSpellCast(unit,unit->X,unit->Y,NoUnitP,
AiEyeOfVision,FlushCommands); AiEyeOfVision,FlushCommands);
return 1;
} }
} }
} }
} }
return 0;
} }
/** /**
** Do magic for paladin. ** Do magic for ogre-mage.
*/ */
local void AiDoPaladin(Unit* unit) local void AiDoOgreMage(Unit* unit)
{
if( AiBloodlustSpell(unit) ) {
return;
}
if( AiEyeOfVisionSpell(unit) ) {
return;
}
}
/**
** Check if the unit should cast the "holy vision" spell.
**
** If the unit has nothing to do and the spell is available and the unit
** has full mana cast with a change of 1/32 the spell. The spells does
** nothing, because the AI cheats and already knows the surroundings.
**
** @param unit Magic unit.
**
** @return True, if a spell is casted.
**
** @note This function can also be used for auto holy vision.
*/
local int AiHolyVisionSpell(Unit* unit)
{ {
int r; int r;
@ -200,10 +252,22 @@ local void AiDoPaladin(Unit* unit)
y=SyncRand()%TheMap.Height; y=SyncRand()%TheMap.Height;
CommandSpellCast(unit,x,y,NoUnitP, CommandSpellCast(unit,x,y,NoUnitP,
AiHolyVision,FlushCommands); AiHolyVision,FlushCommands);
return 1;
} }
} }
} }
} }
return 0;
}
/**
** Do magic for paladin.
*/
local void AiDoPaladin(Unit* unit)
{
if( AiHolyVisionSpell(unit) ) {
return;
}
} }
/** /**

View file

@ -288,6 +288,8 @@ local int AiFindTarget(const Unit* unit,unsigned char* matrix,
} }
// Check targets on tile? // Check targets on tile?
// FIXME: the move code didn't likes a shore building as
// target
if( EnemyOnMapTile(unit,x,y) ) { if( EnemyOnMapTile(unit,x,y) ) {
DebugLevel0Fn("Target found %d,%d-%d\n" DebugLevel0Fn("Target found %d,%d-%d\n"
_C_ x _C_ y _C_ state); _C_ x _C_ y _C_ state);

View file

@ -776,7 +776,7 @@ local SCM CclAiSleep(SCM value)
{ {
int i; int i;
DebugLevel0Fn("%d %d\n",FrameCounter,AiPlayer->SleepFrames); DebugLevel3Fn("%d %d\n",FrameCounter,AiPlayer->SleepFrames);
if( AiPlayer->SleepFrames ) { if( AiPlayer->SleepFrames ) {
if( AiPlayer->SleepFrames<FrameCounter ) { if( AiPlayer->SleepFrames<FrameCounter ) {
AiPlayer->SleepFrames=0; AiPlayer->SleepFrames=0;