AI coding as a platform

Published on Wednesday, January 14, 2015 By Brad Wardell In GalCiv III Dev Journals

Well the party is almost over for you humans.

I’ve never hidden the fact that I consider human beings playing my AI a necessary evil.  I need your money to fund my AI work. Smile

This time around, I’ve got a talented young developer working with me.  He makes me feel old. Very. Very old. 

A lot has changed over the past 20 years.  It is still technically C++ but it’s all very different from what it used to be.

Example code

//GalCiv III:  Example code tags a planet as a potential target.

if(atWar)
        {
            FixedDecimal militaryPower = GetInterface<IStat>(*it)->GetStat(StatTypes::FactionPower, StatUsages::Actual);

            CBasicGameObject* pClosestPlanet = NULL;
            ULONG closestDistance = ULONG_MAX;

            const ObjectPtrList& ownedPlanets = GetInterface<IGC3Player>(*it)->GetOwnedPlanets();
            for(auto planetIt = ownedPlanets.Begin(); planetIt != ownedPlanets.End(); ++planetIt)
            {
                TilePair planetPos = GetInterface<IBasicGameObject>(*planetIt)->GetTilePosition().tile;
               
                BOOL isPlanetInRange = CGalaxy::GetInstance()->GetRangeSystem().IsWithinFleetRangeValue(m_pPlayer, planetPos.posX, planetPos.posY, rangeToUse);
                if(isPlanetInRange)
                {
                    ULONG planetDistance = CWorldSpace::HexDistance(capitalPos, planetPos);
                    if(planetDistance < closestDistance)
                    {
                        closestDistance = planetDistance;
                        pClosestPlanet = (*planetIt);
                    }
                }
            }

            if(pClosestPlanet && militaryPower < weakestPower)
            {
                weakestPower = militaryPower;
                pWeakestPlayer = (*it);
                pTargetPlanet = pClosestPlanet;
            }
        }

 

 

  //GalCiv II: I wrote this to control a transport

//*****************************************************************************
//* AIFindTransportDestination
//* Purpose:
//* Find a planet for a transport to go to
//*****************************************************************************
BOOL classCivilization::AIFindTransportDestination(PclassStarShip pShip)
{
 
   if(pShip->IsInFleet() && !pShip->IsFleet()) return false;


   //Preliminaries: Wait for escorts
   if(pShip->HasDestination() && pShip->IsOrbiting() == FALSE && !pShip->GetAttack() && !AIHostilesInSector(pShip->GetSectorID()) &&  g_pGalaxy->GetDistanceFromFriendlyPlanet(QueryID(),pShip->GetTileX(),pShip->GetTileY())<SECTOR_SIZE && pShip->ulTransportWaitTurns<5)
   {
      pShip->CancelDestination();
      pShip->SetMovesLeft(0);
      return false;
   }

   //Preliminaries: Wait for escorts
   if(pShip->IsOrbiting() == FALSE && !pShip->GetAttack() && !AIHostilesInSector(pShip->GetSectorID()) &&  g_pGalaxy->GetDistanceFromFriendlyPlanet(QueryID(),pShip->GetTileX(),pShip->GetTileY())<SECTOR_SIZE && pShip->ulTransportWaitTurns<5)
   {
      pShip->ulTransportWaitTurns++;
      return false;
   }

   //Step #0: Let's see if there are hostiles near by..
   if(AIHostilesInSector(pShip->GetSectorID()) && pShip->GetAttack()<10 && !pShip->IsOrbiting())
   {
      PclassStarShip pEnemy = pShip->FindClosestLocalEnemyShip(0);

      if (pEnemy && pShip->GetTurnsAway(pEnemy->GetTileX(),pEnemy->GetTileY()) < 2 && pEnemy->GetAttack() > pShip->GetAttack())
      {
         pShip->AITakeEvasiveAction(pEnemy->GetTileX(),pEnemy->GetTileY());
         return TRUE;
      }

   }

   //Step #1: Let's see if there's another undefended planet in sector.
   PclassPlanet pPlanet = AIFindUndefendedEnemyPlanet(pShip->GetSectorID());

 
   if(pPlanet && (!AIHostilesInSector(pPlanet->GetSectorID()) || pShip->GetAttack()>8))
   {
      pShip->CancelDestination();
      pShip->pPlanetDestination = pPlanet;
      return true;
   }

   //Step #2: Let's see where they're currently going.
   pPlanet = pShip->pPlanetDestination;
   if(pPlanet && ulIntelligence<40)
   {
      if(pPlanet->IsDefended() == FALSE && GetRelationsWith(pPlanet->GetOwner()) == AT_WAR)
         return true;
   }

   if(pPlanet)
   {
      if(pPlanet->IsDefended() == TRUE || (AIHostilesInSector(pPlanet->GetSectorID()) && !pShip->GetAttack()) )
         pShip->CancelDestination();
   
   }

 

   //Step #3: Let's look at our primary sector focus and use that.
   if(this->AIulSectorFocuses[0] != INVALID_SECTOR_FOCUS)
   {
        ULONG ulSectorsToFocusOn = this->GetNumSectorFocuses();   
        for (ULONG ulIndex = 0; ulIndex<ulSectorsToFocusOn; ulIndex++)
        {
           ULONG ulSectorID = this->AIulSectorFocuses[ulIndex];
           pPlanet = AIFindUndefendedEnemyPlanet(ulSectorID);
           BOOL bHostilesInSector = false;
           if(pPlanet)
           {
               bHostilesInSector = this->AIHostilesInSector(pPlanet->GetSectorID());


               if(this->ulIntelligence<50 || pShip->GetAttack()>5 )
                  bHostilesInSector = false;
           }
           if(pPlanet && pPlanet->ulAIInvadersAssigned[QueryID()]<4 && !bHostilesInSector )
           {
              pShip->CancelDestination();
              pShip->pPlanetDestination = pPlanet;
              return true;
           }
        }
   }

   //Step #4: Let's see if there are other planets to deal with.
   //Note that we won't go over to sectors with undefended planets
   //IF there are enemy ships in there
   pPlanet = pShip->FindClosestUndefendedEnemyPlanet(0);
   if(pPlanet && (AIHostilesInSector(pPlanet->GetSectorID() == FALSE || pShip->GetAttack()>0)))
   {
         pShip->CancelDestination();
         pShip->pPlanetDestination = pPlanet;
         return true;
   }

   //Step #4: We're AT the Rally Point
   PclassRallyPoint pOnRallyPoint = this->FindNearestRallyPoint(pShip->GetTileX(),pShip->GetTileY());
   if(pOnRallyPoint && pOnRallyPoint->GetDistanceInTiles(pShip) == 0)
   {
      pShip->GoHome();
   }
  
   //Step #5: What if there are hostiles here? Let's retreat
   if(this->AIHostilesInSector(pShip->GetSectorID() && !pShip->GetAttack()))
   {
      pShip->GoHome();
   }
 
   return false;

}