[AI Code] Jungle Bots
I, for one, like to try out new strategies and unusual builds on the bots to get a feel for how they work out without needing to worry about the heaps of insults and accusations that tend to get thrown around by this game's overly competetive aspect (who also include those who yell at others to make up for their own shortcommings.)
Anyway, rant aside, I would like to see the bots use the jungle so as to better approximate a real match. Now, I don't work for Riot and I don't know the exact manner in which they coded the game, but I have attempted to write a bit of pseudo-code that would explain how the AI could work for a jungling bot.
I've broken my pseudo-code into a couple sections:
-
Actual jungling functions for clearing camps.
-
Ganking functions.
-
Champion-specific override functions (using Maokai
as the example).
So, without further ado:
// New Variables float gankThreshold = 1.5; //Determined by difficulty. Higher difficulty adjusts this based on the success of previous ganks. float recallThreshold = 0.30; String jungleSide = "";
//=====General Jungle Functions===== void clearGolemSide() { jungleGolem(); jungleFrog(); jungleWolves(); if (me.blueTeam) checkUpperGanks(); else { checkDragon(); checkLowerGanks(); } } // ---------------------------------------------------------------------------------------------------- void clearLizardSide() { jungleLizard(); jungleBirds(); jungleMiniGolems(); if (me.blueTeam) { checkDragon(); checkLowerGanks(); } else checkUpperGanks(); } // ---------------------------------------------------------------------------------------------------- void checkRecall() checkRecall(0.0); // ---------------------------------------------------------------------------------------------------- void checkRecall(float travelTime) ( if ((me.health + me.healthRegen x travelTime)/me.healthMax < recallThreshold) recall(); ) // ---------------------------------------------------------------------------------------------------- void checkJungleCamp(JungleCamp camp) { if(camp.spawnTime <= travelTime(me.location, camp.center() +3 seconds) jungleCampClear(camp); } // ---------------------------------------------------------------------------------------------------- void checkDragon() { JungleCamp camp = Map.jungleCamp("Dragon", jungleSide); if(camp.spawnTime <= travelTime(me.location, camp.center() +10 seconds) { // I may want another if statement here to ensure that bots don't take on a dragon when under leveled or under fed. me.ping("Help", camp.center()); jungleDragonClear(); } }
//=====Jungle Camp Functions===== void jungleGolem() { checkJungleCamp(Map.jungleCamp("Golem", jungleSide); } void jungleFrog() { jungleCampClear(Map.jungleCamp("Frog", jungleSide); } void jungleWolves() { jungleCampClear(Map.jungleCamp("Wolves", jungleSide); } void jungleLizard() { checkJungleCamp(Map.jungleCamp("Lizard", jungleSide); } void jungleBirds() { jungleCampClear(Map.jungleCamp("Birds", jungleSide); } void jungleMiniGolems() { jungleCampClear(Map.jungleCamp("Mini Golems", jungleSide); } // ---------------------------------------------------------------------------------------------------- void jungleCampClear(JungleCamp camp) // Often overridden by champion-specific function. { checkRecall(travelTime(me.location, camp.center()));
int i =0;
me.attackMove(camp.center());
// Could then use me.attackMove(me.path(-me.attackRange)); to cause ranged junglers to stand back a bit.
while(i <3) // I'm aware of the irony.
{
if(camp.monster[i].name == "Big Golem" || camp.monster[i].name == "Big Lizard" || me.spell("smite").charges ==2) me.spell("smite", camp.monster[i]);
me.attackRoutineNoUltimate(camp.monster[i]);
++i;
}
} // ---------------------------------------------------------------------------------------------------- void jungleDragonClear() // Often overridden by champion-specific function. { checkRecall(travelTime(me.location, camp.center()));
JungleCamp camp = Map.jungleCamp("Dragon", jungleSide);
me.attackMove(camp.center());
me.ping("Attack", camp.center());
me.spell("smite", camp.monster[0]);
me.attackRoutine(camp.monster[0]);
}
//=====Gank Functions===== void checkUpperGanks() { float top, mid;
top = gankability(top)
mid = gankability(mid)
if (top > mid) gankTop();
else gankMid();
} // ---------------------------------------------------------------------------------------------------- void checkLowerGanks() { float mid, bottom;
mid = gankability(mid)
bottom = gankability(bottom)
if (bottom > gankThreshold && bottom > mid) gankBottom();
else if (mid > gankThreshold) gankMid();
} // ---------------------------------------------------------------------------------------------------- float gankability(string lane) //Top, Mid, Bottom { int i =0; float gankability =0; Champion[] enemyChampion = Vision.getEnemyChampions(lane); Champion[] allyChampion = Vision.getAllyChampions(lane);
while(enemyChampion[i] != null)
{
gankability -= enemyChampion[i].healthPercent() x enemyChampion[i].goldSpent(); //Should I use goldEarned() as a measure of skill or goldSpent() as a measure of power?
++i;
}
i =0;
while(allyChampion[i] != null)
{
gankability += allyChampion[i].healthPercent() x allyChampion[i].goldSpent();
++i;
}
gankability += my.healthPercent() x my.goldSpent();
return gankability;
}
//=====Champion Specific Functions===== void junglerInitialize(float gankSkill, float survivability) { gankThreshold = gankSkill; recallThreshold = survivability;
if(me.blueTeam) jungleSide = "Blue Team";
else jungleSide = "Red Team";
} // ---------------------------------------------------------------------------------------------------- void junglerEarlyRoutine() // BlueFirst { void clearGolemSide(); void clearLizardSide(); } // OR void junglerEarlyRoutine() // RedFirst { void clearLizardSide(); void clearGolemSide(); } // ---------------------------------------------------------------------------------------------------- void jungleCampClear(JungleCamp camp) // Maokai override { checkRecall(travelTime(me.location, camp.center()));
int i =0;
me.attackMove(camp.center());
// Maokai pre-sapling
while(camp.spawnTime > me.ability("e").cooldownTime() && camp.spawnTime < 30) me.ability(e, camp.center());
while(i <3)
{
if(camp.monster[i].name == "Big Golem" || camp.monster[i].name == "Big Lizard" || me.spell("smite").charges ==2) me.spell("smite", camp.monster[i]);
me.attackRoutineNoUltimate(camp.monster[i]);
/*while(camp.monster[i] <> null)
{
me.ability("e", camp.monster[i]);
me.ability("w", camp.monster[i]);
me.ability("q", camp.monster[i]);
me.autoAttack(camp.monster[i]);
}*/
++i;
}
} // ---------------------------------------------------------------------------------------------------- void jungleDragonClear() // Maokai override { checkRecall(travelTime(me.location, camp.center()));
JungleCamp camp = Map.jungleCamp("Dragon", jungleSide);
me.attackMove(camp.center());
// Maokai pre-sapling
while(camp.spawnTime > me.ability("e").cooldownTime() && camp.spawnTime < 30) me.ability(e, camp.center());
me.ping("Attack", camp.center());
me.spell("smite", camp.monster[0]);
me.attackRoutine(camp.monster[0]);
}
// End of Code
PS. Sorry about the lack of indentation, I'm not sure how to force indentation. I've put the function names in bold to help distinguish them and I've included separating lines between the larger functions.