forcing certain buildings to be built by AI

kirbdog

King
Joined
Jun 14, 2005
Messages
898
I am trying to force the AI to build the National College and the Hermitage in the capital city when they become available. I'd like any insight.

Here is my first attempt, completely naive and ineffective.

Spoiler :
Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	local pPlayer = Players[ iPlayer ];

	if ( pPlayer:IsHuman() ) then
		return false;
	end

	if ( not pPlayer:CanConstruct( BUILDING_NATIONAL_COLLEGE ) and
	     not pPlayer:CanConstruct( BUILDING_HERMITAGE ) ) then
		return false;
	end

	print("Can build a national wonder");

	local pCapital = pPlayer:GetCapitalCity();

	if ( pPlayer:CanConstruct( BUILDING_NATIONAL_COLLEGE ) ) then
		pCapital:ChooseProduction( 0, BUILDING_NATIONAL_COLLEGE, 0, 1, 1);
		return false;
	end

	if ( pPlayer:CanConstruct( BUILDING_HERMITAGE ) ) then
		pCapital:ChooseProduction( 0, BUILDING_HERMITAGE, 0, 1, 1);
		return false;
	end
end);

I'm not sure how the print statement actually works or how best to debug this and/or go about what I actually want to do.
 
To set the current production you can use PushOrder.

Here is a snippet of how I use it. Apart from the first two parameters, the rest are a mystery which someone else might be able to explain.

Code:
	-- Check if building has any specific orders (i.e. train unit or construct building)
	if cityData.OrderType ~= ORDER_NONE and cityData.OrderType ~= nil then
		print("Production initialized.")
	pCity:PushOrder (cityData.OrderType, cityData.ProdType, -1, 0, false, false)
	else
		print("No production order specified.")
	end
 
Thanks! You're a lifesaver. With that tip, this was relatively painless and easy.

Spoiler :
Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	local pPlayer = Players[ iPlayer ];
	local pCapital = pPlayer:GetCapitalCity();
	local iNationalCollege = GameInfo.Buildings.BUILDING_NATIONAL_COLLEGE.ID;
	local iHermitage = GameInfo.Buildings.BUILDING_HERMITAGE.ID;

	if ( pPlayer:IsHuman() ) then
		return false;
	end

	if ( not pPlayer:CanConstruct( iNationalCollege ) and
	     not pPlayer:CanConstruct( iHermitage ) ) then
		return false;
	end

	if ( pPlayer:CanConstruct( iNationalCollege ) ) then
		pCapital:PushOrder( OrderTypes.ORDER_CONSTRUCT, iNationalCollege, 0, 1, 1);
		return false;
	end

	if ( pPlayer:CanConstruct( iHermitage ) ) then
		pCapital:PushOrder( OrderTypes.ORDER_CONSTRUCT, iHermitage, 0, 1, 1);
		return false;
	end
end);

This seems to work!
 
Thanks, Hambil, I appreciate it.

Apparently the AI makes building choices before PlayerDoTurn happens. There was a bug when the AI started construction on the National College right after building the last library. This code addresses that.

Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	local pPlayer = Players[ iPlayer ];
	local pCapital = pPlayer:GetCapitalCity();
	local iNationalCollege = GameInfoTypes.BUILDING_NATIONAL_COLLEGE;
	local iHermitage = GameInfoTypes.BUILDING_HERMITAGE;

	if ( pPlayer:IsHuman() ) then
		return false;
	end

	-- the 1 flag means that under construction still returns true
	if ( not pPlayer:CanConstruct( iNationalCollege, 1 ) and
	     not pPlayer:CanConstruct( iHermitage, 1 ) ) then
		return false;
	end

	local function ForceBuildInCity( pPlayer, pCapital, iBuildingType )
		if ( pCapital:CanConstruct( iBuildingType ) ) then
			pCapital:PushOrder( OrderTypes.ORDER_CONSTRUCT, iBuildingType, 0, 1, 1);
			return false;
		end

		for pCity in pPlayer:Cities() do
			if ( pCity.GetFirstBuildingOrder( iBuildingType ) == 0 ) then
				pCity.PopOrder( 0, 0, 1 );
				pCapital:PushOrder( OrderTypes.ORDER_CONSTRUCT, iBuildingType, 0, 1, 1);
				return false;
			end
		end
	end

	if ( pPlayer:CanConstruct( iNationalCollege, 1 ) ) then
		ForceBuildInCity( pPlayer, pCapital, iNationalCollege );
		return false;
	end

	if ( pPlayer:CanConstruct( iHermitage, 1 ) ) then
		ForceBuildInCity( pPlayer, pCapital, iHermitage );
		return false;
	end
end);

I am not sure, but a turn of production might be wasted when using PopOrder and not setting something to build. The AI doesn't seem to use queues.
 
Rather than aborting builds of the National College or the Hermitage in AI non-capital cities, use GameEvents.CityCanConstruct() to stop them being built there in the first place

Code:
local iNationalCollege = GameInfoTypes.BUILDING_NATIONAL_COLLEGE
local iHermitage = GameInfoTypes.BUILDING_HERMITAGE

function OnCityCanConstruct(iPlayer, iCity, iBuilding)
  -- Let human players make their own decisions
  local pPlayer = Players[iPlayer]
  if (pPlayer:IsHuman()) then
    return true
  end

  -- AI non-capital cities may never build the National College or the Hermitage
  local pCity = pPlayer:GetCityByID(iCity)
  if (not pCity:IsCapital()) then
    return not (iBuilding == iNationalCollege or iBuilding == iHermitage)
  end
  
  -- The AI can build anything it likes in the capital
  return true
end
GameEvents.CityCanConstruct.Add(OnCityCanConstruct)

Your PlayerDoTurn function now only has to worry about making the AI build the National College or Hermitage in the capital when appropriate
 
A word of warning ...

Do not try to use the CityCanConstruct() event to stop the capital building anything but the National College or the Hermitage if it can build either of those buildings (which at first glance seems a logical approach), as within that logic you will need to ascertain if the capital can build either of those two buildings which will in turn call GameEvents.CityCanConstruct()
 
Back
Top Bottom