Skip to content

Instantly share code, notes, and snippets.

@commana
Last active August 29, 2015 14:02
Show Gist options
  • Save commana/768298782abc3d9cb95e to your computer and use it in GitHub Desktop.
Save commana/768298782abc3d9cb95e to your computer and use it in GitHub Desktop.
My collection of CodeCombat scripts
// This code runs once per frame. Build units and command peons!
// Destroy the human base within 180 seconds.
// Run over 4000 statements per call and chooseAction will run less often.
// Check out the green Guide button at the top for more info.
var base = this;
function sortByCoinValue(a, b) {
return b.coin.bountyGold - a.coin.bountyGold;
}
function sortByDistance(a, b) {
return a.distance - b.distance;
}
/////// 1. Command peons to grab coins and gems. ///////
// You can only command peons, not fighting units.
// You win by gathering gold more efficiently to make a larger army.
// Click on a unit to see its API.
var allItems = base.getItems();
var peons = base.getByType('peon');
var peasants = base.getByType('peasant');
var enemies = base.getEnemies();
// filter all items that are targeted by peasants, and that we won't reach in time
var unreachablePositions = [];
for (var pi = 0; pi < peasants.length; pi++) {
var peasant = peasants[pi];
if (!peasant.targetPos) {
continue;
}
// we want to use indexOf, but it doesn't seem to work directly with Vector objects
var posId = peasant.targetPos.x + "," + peasant.targetPos.y + "," + peasant.targetPos.z;
var peasantTargetDistance = peasant.pos.distance(peasant.targetPos);
var potentiallyUnreachablePositions = [];
var reachablePositions = [];
for (var pj = 0; pj < peons.length; pj++) {
var peon = peons[pj];
var peonTargetDistance = peon.pos.distance(peasant.targetPos);
if (peonTargetDistance > peasantTargetDistance) {
potentiallyUnreachablePositions.push(posId);
} else {
reachablePositions.push(posId);
}
}
for (var ti = 0; ti < potentiallyUnreachablePositions.length; ti++) {
if (reachablePositions.indexOf(potentiallyUnreachablePositions[ti]) === -1) {
unreachablePositions.push(potentiallyUnreachablePositions[ti]);
}
}
}
items = allItems.filter(function(i) {
var posId = i.pos.x + "," + i.pos.y + "," + i.pos.z;
return unreachablePositions.indexOf(posId) === -1;
});
// divide the playing field by number of peons
// we divide it by x coords
var maxX = 90;
var numPlayingFields = peons.length;
var fieldWidth = maxX / numPlayingFields;
var fields = [];
for (var fieldIndex = 0; fieldIndex < numPlayingFields; fieldIndex++) {
var itemsForField = [];
// find all coins in the specified x range
for (var i = 0; i < items.length; i++) {
var startX = fieldIndex * fieldWidth;
var endX = fieldIndex * fieldWidth + fieldWidth;
if (items[i].pos.x >= startX && items[i].pos.x < endX) {
itemsForField.push(items[i]);
}
}
fields.push(itemsForField);
}
// build a list that is sorted by nearest coin to peon
var peonTasks = [];
for (var i = 0; i < peons.length; i++) {
var peon = peons[i];
var coins = fields[i];
var nearestPositions = [];
for (var ii = 0; ii < coins.length; ii++) {
nearestPositions.push({ coin: coins[ii], distance: peon.pos.distance(coins[ii].pos) });
}
nearestPositions.sort(sortByDistance);
var positions = nearestPositions;
// find all gems, they are always our primary target
var gems = nearestPositions.filter(function(p) {
return p.coin.bountyGold === 5;
});
// go after high value coins, consider copper only if in immediate vicinity
var highValuePositions = nearestPositions.filter(function(p) {
if (p.distance < 7) return true;
if (p.coin.bountyGold === 1) return false;
if (p.coin.bountyGold === 2 && p.distance > 12) return false;
return true;
});
if (highValuePositions.length === 0) {
if (gems.length === 0) {
// there are no primary targets
positions = nearestPositions;
} else {
// go after the gems
positions = gems;
}
} else {
if (gems.length === 0) {
positions = highValuePositions;
} else {
var primaryTarget = gems[0].coin;
// collect coins along the way, but stay on the current direction
var highValuesInDirection = highValuePositions.filter(function(p) {
var targetVector = Vector.subtract(peon.pos, primaryTarget.pos);
var direction = Vector.normalize(targetVector);
var coinVector = Vector.subtract(peon.pos, p.coin.pos);
var coinDirection = Vector.normalize(coinVector);
return Math.abs(direction.heading() - coinDirection.heading()) <= Math.PI/8;
});
if (highValuesInDirection.length === 0) {
positions = gems;
} else {
positions = highValuesInDirection;
}
}
}
peonTasks.push({ peon: peon, positions: positions });
}
for (var j = 0; j < peonTasks.length; j++) {
var task = peonTasks[j];
if (task.positions.length) {
base.command( task.peon, 'move', task.positions[0].coin.pos);
}
}
/////// 2. Decide which unit to build this frame. ///////
// Peons can gather gold; other units auto-attack the enemy base.
// You can only build one unit per frame, if you have enough gold.
var type;
var buildOrder = ["peon", "peon", "peon", "munchkin", "munchkin", "munchkin", "munchkin"];
type = buildOrder[this.built.length % buildOrder.length];
if (base.gold >= base.buildables[type].goldCost)
base.build(type);
// 'peon': Peons gather gold and do not fight.
// 'munchkin': Light melee unit.
// 'ogre': Heavy melee unit.
// 'shaman': Support spellcaster.
// 'fangrider': High damage ranged attacker.
// 'brawler': Mythically expensive super melee unit.
// See the buildables documentation below for costs and the guide for more info.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment