4、营地产生的野蛮人单位的条件及类型、位置
这段代码在DoSpawnBarbarianUnit()函数中,总第659~777行,调用条件是某地块的m_aiPlotBarbCampSpawnCounter为0(m_aiPlotBarbCampSpawnCounter解释见0):- int iNumNearbyUnits;
- int iNearbyUnitLoop;
- int iRange = GC.getMAX_BARBARIANS_FROM_CAMP_NEARBY_RANGE();
- int iX;
- int iY;
- CvPlot* pNearbyPlot;
- DirectionTypes eDirection;
- CvGame& kGame = GC.getGame();
- if (pPlot == 0)
- return;
- // is this camp empty - first priority is to fill it
- if (pPlot && pPlot->GetNumCombatUnits() == 0)
- {
- UnitTypes eUnit;
- eUnit = GetRandomBarbarianUnitType(GC.getMap().getArea(pPlot->getArea()), UNITAI_FAST_ATTACK);
- if (eUnit != NO_UNIT)
- {
- CvUnit* pUnit = GET_PLAYER(BARBARIAN_PLAYER).initUnit(eUnit, pPlot->getX(), pPlot->getY(), UNITAI_FAST_ATTACK);
- pUnit->finishMoves();
- return;
- }
- }
- m_aeValidBarbSpawnDirections.clear();
- // Look at nearby Plots to see if there are already too many Barbs nearby
- iNumNearbyUnits = 0;
- for(iX = -iRange; iX <= iRange; iX++)
- {
- for(iY = -iRange; iY <= iRange; iY++)
- {
- // Cut off the corners of the area we're looking at that we don't want
- pNearbyPlot = plotXYWithRangeCheck(pPlot->getX(), pPlot->getY(), iX, iY, iRange);
- if(pNearbyPlot != NULL)
- {
- if(pNearbyPlot->getNumUnits() > 0)
- {
- for(iNearbyUnitLoop = 0; iNearbyUnitLoop < pNearbyPlot->getNumUnits(); iNearbyUnitLoop++)
- {
- const CvUnit* const unit = pNearbyPlot->getUnitByIndex(iNearbyUnitLoop);
- if(unit && pNearbyPlot->getUnitByIndex(iNearbyUnitLoop)->isBarbarian())
- {
- iNumNearbyUnits++;
- }
- }
- }
- }
- }
- }
- if(iNumNearbyUnits <= /*2*/ GC.getMAX_BARBARIANS_FROM_CAMP_NEARBY())
- {
- CvPlot* pLoopPlot;
- // Barbs only get boats after some period of time has passed
- bool bCanSpawnBoats = kGame.getElapsedGameTurns() > /*30*/ GC.getBARBARIAN_NAVAL_UNIT_START_TURN_SPAWN();
- // Look to see if adjacent Tiles are valid locations to spawn a Unit
- for(int iDirectionLoop = 0; iDirectionLoop < NUM_DIRECTION_TYPES; iDirectionLoop++)
- {
- eDirection = (DirectionTypes) iDirectionLoop;
- pLoopPlot = plotDirection(pPlot->getX(), pPlot->getY(), eDirection);
- if(pLoopPlot != NULL)
- {
- if(pLoopPlot->getNumUnits() == 0)
- {
- if(!pLoopPlot->isImpassable() && !pLoopPlot->isMountain())
- {
- if(!pLoopPlot->isCity())
- {
- if(!pLoopPlot->isLake())
- {
- // Water Tiles are only valid when the Barbs have the proper Tech
- if(!pLoopPlot->isWater() || bCanSpawnBoats)
- {
- m_aeValidBarbSpawnDirections.push_back(eDirection);
- }
- }
- }
- }
- }
- }
- }
- // Any valid locations?
- if(m_aeValidBarbSpawnDirections.size() > 0)
- {
- int iIndex = kGame.getJonRandNum(m_aeValidBarbSpawnDirections.size(), "Barb Unit Location Spawn Roll");
- eDirection = (DirectionTypes) m_aeValidBarbSpawnDirections[iIndex];
- CvPlot* pSpawnPlot = plotDirection(pPlot->getX(), pPlot->getY(), eDirection);
- UnitAITypes eUnitAI;
- UnitTypes eUnit;
- // Naval Barbs
- if(pSpawnPlot->isWater())
- {
- eUnitAI = UNITAI_ATTACK_SEA;
- }
- // Land Barbs
- else
- {
- eUnitAI = UNITAI_FAST_ATTACK;
- }
- eUnit = GetRandomBarbarianUnitType(GC.getMap().getArea(pSpawnPlot->getArea()), eUnitAI);
- if(eUnit != NO_UNIT)
- {
- CvUnit* pUnit = GET_PLAYER(BARBARIAN_PLAYER).initUnit(eUnit, pSpawnPlot->getX(), pSpawnPlot->getY(), eUnitAI);
- }
- }
- }
复制代码 其中,iRange=MAX_BARBARIANS_FROM_CAMP_NEARBY_RANGE=4;BARBARIAN_NAVAL_UNIT_START_TURN_SPAWN=2;BARBARIAN_NAVAL_UNIT_START_TURN_SPAWN=30
1.当前地块是否有野蛮人单位?
(1).没有,在当前地块产生UNITAI_FAST_ATTACK类型的单位,函数返回
(2).有,继续执行
2.检查附近4(MAX_BARBARIANS_FROM_CAMP_NEARBY_RANGE)格范围内的野蛮人单位的数量,如果小于2(MAX_BARBARIANS_FROM_CAMP_NEARBY)个
(1).逐个检查临近地块,若符合以下条件:
a.无单位
b.可通行
c.非山峰
d.非城市
e.非湖泊
f.非水域和可产生船只之间满足一项(可产生船只的条件是已经过的回合数大于30)
则将该地块加入可产生单位地块队列中
3.如果可产生单位地块队列长度不为0
1.产生一个0~队列长度-1的随机数
2.此地块是否为水域?
a.是,产生UNITAI_ATTACK_SEA类型的单位
b.否,产生UNITAI_FAST_ATTACK类型的单位
UNITAI_FAST_ATTACK和UNITAI_ATTACK_SEA是AI所使用的单位类型,具体有哪些请参阅相关帖子(虽然貌似目前还没有- -)
另外注意一点如果到时间没有产生野蛮人计数器会一直保持在0,也就是说,只要在之后的某个回合满足条件,就会生成野蛮人
结论:
1.营地野蛮人生成的条件:达到生成的回合数,且4格内有少于或等于2个的蛮族单位,且临近地块或当前地块有可以放置野蛮人单位的地块;
2.别过度吸引野蛮人的注意,如果他们远离营地会使营地继续产生野蛮人;
3.30回合后小心野蛮人的战船。
[ 本帖最后由 Olemi 于 2012-11-8 23:36 编辑 ] |