extern void object::NohusBattleMain() { point converterPos; point powerPlantPos; point researchCenterPos; point botFactoryPos; point powerStationPos; point centerPos; int orientationLeft; int orientationRight; int orientationBack; int xTeamInversion; string teamName; if (position.y < 0) { // Blue team teamName = "Blue"; xTeamInversion = 1; orientationLeft = 0; orientationRight = 180; orientationBack = 90; converterPos.x = 5; converterPos.y = -50.5; powerPlantPos.x = -5; powerPlantPos.y = -51; researchCenterPos.x = 7; researchCenterPos.y = -41.5; botFactoryPos.x = -8; botFactoryPos.y = -42; powerStationPos.x = 0; powerStationPos.y = -33; centerPos.x = 0; centerPos.y = -45; } else { // Red team teamName = "Red"; xTeamInversion = -1; orientationLeft = 180; orientationRight = 0; orientationBack = 270; converterPos.x = -5; converterPos.y = 50.5; powerPlantPos.x = 5; powerPlantPos.y = 51; researchCenterPos.x = -7; researchCenterPos.y = 41.5; botFactoryPos.x = 8; botFactoryPos.y = 42; powerStationPos.x = 0; powerStationPos.y = 33; centerPos.x = 0; centerPos.y = 45; } message("[Nohus]: Set up for the " + teamName + " team"); while (energyCell.energyLevel == 0) wait(0.01); int startTime = abstime(); message("[Nohus]: Battle started"); grab(); buildAt(Converter, converterPos, orientationLeft); makeTitanium(converterPos); getTitanium(converterPos); buildAt(PowerPlant, powerPlantPos, orientationRight); makeTitanium(converterPos); getTitanium(converterPos); buildAt(ResearchCenter, researchCenterPos, orientationLeft); makeTitanium(converterPos); getTitanium(converterPos); makePowerCell(powerPlantPos); makeTitanium(converterPos); getPowerCell(powerPlantPos); point researchCenterFront = researchCenterPos; researchCenterFront.x -= (4 * xTeamInversion); fastGoto(researchCenterFront, 0); absoluteTurn(orientationLeft); drop(); object researchCenter = radar(ResearchCenter); researchCenter.research(ResearchWinged); while(!researched(ResearchWinged)) wait(0.05); grab(); turn(-90); move(3); turn(90); drop(); getTitanium(converterPos); makePowerCell(powerPlantPos); makeTitanium(converterPos); getPowerCell(powerPlantPos); fastGoto(researchCenterFront, 0); absoluteTurn(orientationLeft); drop(); researchCenter.research(ResearchShooter); point converterFront = converterPos; converterFront.x -= (2 * xTeamInversion); fastGoto(converterFront, 0); getTitanium(converterPos); makePowerCell(powerPlantPos); makeTitanium(converterPos); getTitanium(converterPos); buildAt(BotFactory, botFactoryPos, orientationRight); buildShooter(converterPos, powerPlantPos, botFactoryPos, xTeamInversion, orientationRight); message("[Nohus]: Activated shooter #1 (" + battleTime(startTime) + ")"); makeTitanium(converterPos); getTitanium(converterPos); fastGoto(centerPos, 0); buildAt(PowerStation, powerStationPos, orientationBack); int shooter = 1; while (true) { buildShooter(converterPos, powerPlantPos, botFactoryPos, xTeamInversion, orientationRight); shooter++; message("[Nohus]: Activated shooter #" + shooter + " (" + battleTime(startTime) + ")"); if (energyCell.energyLevel < 0.3) { fastGoto(powerStationPos, 0); while(energyCell.energyLevel < 1) wait(0.05); } } } void buildShooter(point converterPos, point powerPlantPos, point botFactoryPos, int xTeamInversion, int orientationRight) { makeTitanium(converterPos); getTitanium(converterPos); object powerPlant = radar(PowerPlant, 0, 360, 0, 1000, 1, FilterFriendly); if (powerPlant.energyCell == null) { makePowerCell(powerPlantPos); makeTitanium(converterPos); getTitanium(converterPos); } point botFactoryFront = botFactoryPos; botFactoryFront.x += (5 * xTeamInversion); fastGoto(botFactoryFront, 0); fastGoto(botFactoryPos, 3.5); drop(); move(-2.5); object botFactory = radar(BotFactory); botFactory.factory(WingedShooter, "NohusBattleShooter"); move(-1); getPowerCell(powerPlantPos); fastGoto(converterPos, 5); fastGoto(botFactoryFront, 3); move(2); absoluteTurn(orientationRight); object shooter = radar(WingedShooter, 0, 45, 0, 10, 1, FilterFriendly); while (shooter == null) { shooter = radar(WingedShooter, 0, 45, 0, 10, 1, FilterFriendly); wait(0.05); } fastGoto(botFactoryPos, 3.5); drop(); move(-4); } void makeTitanium(point converterPos) { object titaniumOre = null; while(titaniumOre == null) { titaniumOre = radar(TitaniumOre); } fastGoto(titaniumOre.position, 1.7); grab(); fastGoto(converterPos, 3.5); drop(); move(-1.5); } void getTitanium(point converterPos) { fastGoto(converterPos, 4); object titanium = null; while(titanium == null) { titanium = radar(Titanium, 0, 45, 0, 5); } fastGoto(titanium.position, 1.6); grab(); } void buildAt(int category, point position, float angle) { fastGoto(position, 0); absoluteTurn(angle); move(-1.5); drop(); build(category); } void makePowerCell(point powerPlantPos) { fastGoto(powerPlantPos, 2.7); drop(); } void getPowerCell(point powerPlantPos) { fastGoto(powerPlantPos, 2.7); object powerPlant = radar(PowerPlant); while (powerPlant.energyCell.energyLevel < 1) wait(0.05); grab(); } void object::fastGoto(point target, float dist) { if (dist == 0) { dist = 0.1; } turn(direction(target)); float distNow = 10000; float enginePower; do { distNow = distance2d(this.position, target); enginePower = scaleValue(distNow, 4, 1); if (enginePower < 0.2) { enginePower = 0.2; } motor(enginePower, enginePower); // message("Distance: " + (distNow - dist) + " Target: " + dist); wait(0.05); } while(distNow > dist); motor(0, 0); if (enginePower == 1) { message("[Nohus]: Slow down time! Goto overshot by: " + (-1 *(distNow - dist)), DisplayWarning); } } void object::absoluteTurn(float angle) { float delta = this.orientation - angle; if (delta > 180) { delta = delta - 360; } turn(-1 * delta); // float enginePower = 0; // while(abs(delta) > 0.5) { // enginePower = scaleValue(abs(delta), 50, 1); // if (enginePower < 0.05) { // enginePower = 0.05; // } // if (delta > 0) { // motor(enginePower, -1 * enginePower); // } else { // motor(-1 * enginePower, enginePower); // } // float lastDelta = abs(delta); // delta = this.orientation - angle; // if (delta > 180) { // delta = delta - 360; // } // if (abs(delta) > lastDelta) { // message("Turn overshot by " + abs(delta) + "°" + " Engine: " + enginePower, DisplayWarning); // break; // Overshot the turn, do not correct // } // } // motor(0, 0); // message(this.orientation + " --> " + angle); // message("Angle: " + delta + " Engine power: " + enginePower); } float scaleValue(float value, float scale, float scaleMax) { if (value >= scale) { return scaleMax; } float factor = scaleMax / scale; return value * factor; } // WingedShooter program public void object::NohusBattleShooter() { while (energyCell == null) wait(0.05); wait(2); move(-4); jet(0.2); while (position.z < 10) wait(0.05); jet(0); object enemy = null; object obstacle = null; object bottomObstacle = null; int cannonAngle = 0; int target = 0; int threats[3]; threats[0] = WingedShooter; threats[1] = TrackedShooter; threats[2] = WheeledShooter; while (true) { do { enemy = radar(BotFactory, 0, 360, 0, 1000, 1, FilterEnemy); if (enemy == null) { enemy = radar(threats, 0, 360, 0, 1000, 1, FilterEnemy); if (enemy == null) { enemy = radar(WheeledGrabber, 0, 360, 0, 1000, 1, FilterEnemy); if (enemy == null) { enemy = radar(Any, 0, 360, 0, 1000, 1, FilterEnemy); } } } if (enemy.category != target) { target = enemy.category; message("[Nohus]: Targeting enemy " + target); } obstacle = radar(Any, 0, 360, 0, 10, 1, FilterFriendly | FilterNeutral); if (obstacle != null) { if (position.z - obstacle.position.z < 6) { message("[Nohus]: Avoiding obstacle: " + obstacle.category); jet(0.2); while(position.z - obstacle.position.z < 6) wait(0.05); jet(0); } else { obstacle = null; } } // bottomObstacle = radar(Any, 0, 360, 0, 10); // if ((bottomObstacle != null) && (position.z - bottomObstacle.position.z < 5)) { // message("Avoiding bottom obstacle: " + bottomObstacle.category); // motor(0, 0); // jet(0.4); // while(position.z - bottomObstacle.position.z < 5); // jet(0); // } else { // bottomObstacle = null; // } int angle = direction(enemy.position); float dist2d = distance2d(position, enemy.position); float dist = distance(position, enemy.position); float heightDist = position.z - enemy.position.z; float engineLeft = 0; float engineRight = 0; float engineJet = 0; if (angle > 2.5) { engineLeft -= 0.3; engineRight += 0.3; } else if (angle < -2.5) { engineLeft += 0.3; engineRight -= 0.3; } if (dist > 35) { engineLeft += 0.5; engineRight += 0.5; } else if (dist < 25 && (engineLeft == engineRight)) { engineLeft -= 0.5; engineRight -= 0.5; } if (heightDist > 10) { engineJet = -0.2; } else if (heightDist < -1) { engineJet = 0.2; } motor(engineLeft, engineRight); if (obstacle == null || engineJet >= 0) { jet(engineJet); } else if (obstacle != null) { jet(0); } float verticalAngle = -1 * verticalDirection(dist2d, dist); float diff = cannonAngle - verticalAngle; if (abs(diff) > 2) { aim(verticalAngle); cannonAngle = verticalAngle; } if (engineLeft == engineRight && engineJet == 0 && dist < 40) { if (cannonAngle >= -20 || cannonAngle <= 20) { fire(0.1); } } } while(enemy != null && energyCell.energyLevel > 0.25); object powerStation = radar(PowerStation/*, 0, 360, 0, 1000, 1, FilterFriendly*/); goto(powerStation.position); while (energyCell.energyLevel < 1) wait(0.05); } } int verticalDirection(float dist2d, float dist) { float sine = dist2d / dist; float angle = asin(sine); return 90 - angle; } float abs(float number) { return sqrt(pow(number, 2)); } string battleTime(int startTime) { int seconds = abstime() - startTime; int minutes = seconds / 60; seconds %= 60; return minutes + "m " + seconds + "s"; }