Last active
August 29, 2015 14:02
-
-
Save sunzenshen/69162943e479c78cf86a to your computer and use it in GitHub Desktop.
CodeCombat Greed Competition Entry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code runs once per frame. Build units and command collectors! | |
// Destroy the enemy base within 180 seconds. | |
// Run over 4000 statements per call and chooseAction will run less often. | |
var base = this; | |
/////// 0. Determine which team is in play | |
// Ogres Team | |
var collectorType = 'peon'; | |
var scoutType = 'munchkin'; | |
var nobleType = 'ogre'; | |
var casterType = 'shaman'; | |
var flyerType = 'fangrider'; | |
var titanType = 'brawler'; | |
/* | |
// Humans Team | |
var collectorType = 'peasant'; | |
var scoutType = 'soldier'; | |
var nobleType = 'knight'; | |
var casterType = 'librarian'; | |
var flyerType = 'griffin-rider'; | |
var titanType = 'captain'; | |
*/ | |
/////// 1. Command collectors to grab coins and gems. /////// | |
// You can only command collectors, not fighting units. | |
// You win by gathering gold more efficiently to make a larger army. | |
// Click on a unit to see its API. | |
var items = base.getItems(); | |
var collectors = base.getByType(collectorType); | |
// At the time, I thought that collectors could only move toward an item, | |
// and not towards an xy coordinate. | |
var topLeft; | |
var topRight; | |
var lowLeft; | |
var lowRight; | |
for (var collectorIndex = 0; collectorIndex < collectors.length; collectorIndex++) { | |
var collector = collectors[collectorIndex]; | |
var item = collector.getNearest(items); | |
var itemIndex = 0; | |
var itemCandidate; | |
// Figure out which items are in the 4 corners of the map. | |
// This was before I heard an XY coordinate could be used for movement. | |
if (collectorIndex === 0) { | |
for (itemIndex = 0; itemIndex < items.length; itemIndex++) { | |
itemCandidate = items[itemIndex]; | |
topLeft = item.pos; | |
topRight = item.pos; | |
lowLeft = item.pos; | |
lowRight = item.pos; | |
if ((lowLeft.x > itemCandidate.pos.x) && (lowLeft.y > itemCandidate.pos.y)) { | |
lowLeft = itemCandidate.pos; | |
} | |
if ((topRight.x < itemCandidate.pos.x) && (topRight.y < itemCandidate.pos.y)) { | |
topRight = itemCandidate.pos; | |
} | |
if ((lowRight.x < itemCandidate.pos.x) && (lowRight.y > itemCandidate.pos.y)) { | |
lowRight = itemCandidate.pos; | |
} | |
if ((topLeft.x > itemCandidate.pos.x) && (topLeft.y < itemCandidate.pos.y)) { | |
topLeft = itemCandidate.pos; | |
} | |
} | |
} | |
// Determine if collectors are too close together. | |
var clusterDistance = 9999; | |
for (var collector2Index = 0; collector2Index < collectorIndex; collector2Index++) { | |
var collector2 = collectors[collector2Index]; | |
if (clusterDistance > collector2.distance(collector)) { | |
clusterDistance = collector2.distance(collector); | |
} | |
} | |
if((clusterDistance < 50)) { | |
// If a collector is too close to another, | |
// then try to move to a pre-assigned quadrant. | |
if (collectorIndex === 0) { | |
base.command(collector, 'move', topLeft); | |
} else if (collectorIndex === 1) { | |
base.command(collector, 'move', lowRight); | |
} else if (collectorIndex === 2) { | |
base.command(collector, 'move', lowLeft); | |
} else if (collectorIndex === 3) { | |
base.command(collector, 'move', topRight); | |
} | |
} else if (collector.distance(item) > 10*item.bountyGold) { | |
// If current collector is not near any items, | |
// figure out which direction most of the items are. | |
var xWeight = 0; | |
var yWeight = 0; | |
for (itemIndex = 0; itemIndex < items.length; itemIndex++) { | |
itemCandidate = items[itemIndex]; | |
if (collector.pos.x < itemCandidate.pos.x){ | |
xWeight = xWeight + itemCandidate.bountyGold; | |
} else { | |
xWeight = xWeight - itemCandidate.bountyGold; | |
} | |
if (collector.pos.y < itemCandidate.pos.y){ | |
yWeight = yWeight + itemCandidate.bountyGold; | |
} else { | |
yWeight = yWeight - itemCandidate.bountyGold; | |
} | |
} | |
// Then command the collector to move towards the direction with the most items. | |
if (xWeight > 0) { | |
if (yWeight > 0) { | |
base.command(collector, 'move', topRight); | |
} else { // yWeight <= 0 | |
base.command(collector, 'move', lowRight); | |
} | |
} else { // xWeight <= 0 | |
if (yWeight > 0) { | |
base.command(collector, 'move', topLeft); | |
} else { // yWeight <= 0 | |
base.command(collector, 'move', lowLeft); | |
} | |
} | |
} else { | |
// Within a threshold based on item value, move the collector to the nearest item. | |
base.command(collector, 'move', item.pos); | |
} | |
} | |
/////// 2. Decide which unit to build this frame. /////// | |
// Collectors 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; | |
if (base.built.length === 0) { | |
type = collectorType; | |
} | |
else { | |
if ((base.health < 300) || | |
(base.gold > 100) || | |
(base.getByType(scoutType).length > 1)) { | |
// I went with a set build order that is triggered on attack or economic threshold. | |
if(base.getByType(scoutType).length < 3) { | |
type = scoutType; | |
} else if(base.getByType(nobleType).length < 2) { | |
type = nobleType; | |
} else if(base.getByType(casterType).length < 1) { | |
type = casterType; | |
} else if(base.getByType(flyerType).length < 1) { | |
type = flyerType; | |
} else { | |
type = casterType; | |
} | |
} else if (base.getByType(collectorType).length < 2) { | |
type = collectorType; | |
} else if ((base.getByType(collectorType).length >= 2) && | |
(base.getByType(scoutType).length < 1)) { | |
// Given a self-imposed max of 2 collectors, | |
// a light unit is sent to poke the enemy's defenses. | |
type = scoutType; | |
} | |
} | |
var toBuild = base.buildables[type]; | |
if (type && (base.gold >= toBuild.goldCost)) { | |
base.build(type); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This was my entry for CodeCombat's Greed competition. Despite its half finished state, I ended up winning a free E-book from O'Reilly. My final rank on the Ogres team was #56 with 269 wins, 129 losses, and 9 ties.
Check out the "revisions" viewer for the original competition submission, as well as my updates since then.
Final ladder rankings:
http://codecombat.com/play/ladder/greed#winners
A writeup on approaches more skilled than mine:
http://blog.codecombat.com/a-31-trillion-390-billion-statement-programming-war-between-545-wizards