// Humble Programmer's ULTRADUCK v2.0
// For Blocky Games JSPond: https://blockly-games.appspot.com/pond-advanced?lang=en&level=10
// Given a direction we are currently moving in (runDirection)
// Choose a new direction to go in so that we make sure we're
// not going to crash into a wall
function chooseDirection(runDirection){
// Get our current position:
var x = loc_x();
var y = loc_y();
// Make sure values are between 0-360;
// Convert values like -20 or 380 to
// 340 or 20
while(runDirection < 0)
runDirection += 360;
while(runDirection > 360)
runDirection -= 360;
if(x<30 && runDirection>90 && runDirection<270) {
// If we're near the left edge and we're moving left
// then turn 180 degrees so we don't hit the wall
runDirection -= 180;
} else if(x>70 && (runDirection<90 || runDirection>270)) {
// If we're close to the right wall and we;re moving right
// then our new direction should be the opposite way
runDirection -= 180;
}
if(y>70 && runDirection>0 && runDirection<180) {
// If we're near the top of the pond and moving up,
// change directions and go down
runDirection += 180;
} else if(y<30 && runDirection>180 && runDirection<360) {
// And the opposite if we're near the bottom
runDirection -= 180;
}
return runDirection;
}
// This function returns the next angle to scan for enemies at
// This is where the heart of the target acquision is
// This is a closure: It has variables within it that hold their
// valuse between calls to the function
var nextScanAngle = (function(){
// Closure variables: These will keep their state after calls
// to nextScanAngle()
// How many degrees to scan by on each pass
var scanRate = 10;
// What angle we're using as our base angle
var baseAngle = 0;
// iterator, to keep track of if this is an even/odd call
var i = 0;
// The actual function logic:
return function() {
// We want to alternate scanning forward and back, adjusting by
// scanRate degrees each time. We use our itterator to do so.
// Flip the iterator between 1 or 0:
if((i = (i+1)%2)) {
// If it's 1, return the opposite of the base angle
return baseAngle + 180;
} else {
// If it's 0, adjust the base angle by the scan rate and return that
return baseAngle+=scanRate;
}
};
})();
// Main program's variables:
// Angle we're looking for enemies at:
var angle = 0;
// Distance to the nearest enemy:
var distance = Infinity;
// How much health we had last time we checked and if we got hurt
var lastHealth = health(), gotHurt = false;
// Are we running away, and in what direction?
var running = 0, runDirection = 0;
// How fast to run away when scared
var runSpeed = 100;
// Main program:
while(1){
// Have we been hit?
if (health() < lastHealth) {
// If so, choose a random direction and run for 25 loops
runDirection = Math.random()*360;
running = 25;
// Make a note of our current health because we've been hurt
lastHealth = health();
}
// If we're running away
if(running) {
// Make sure the direction we're running is a good choice,
// and then swim in that direction
runDirection = chooseDirection(runDirection);
swim(runDirection,runSpeed);
// While we're running away we might as well look for targets
distance = scan(angle,20);
if(distance == Infinity) {
// We couldn't find a target at our last angle, so get a new angle
angle = nextScanAngle();
} else if(distance<40) {
// We have a nearby enemy, so shoot at them!
cannon(angle,distance);
}
// Decrement our running counter, when it hits zero we stop running
running--;
} else {
// We're not running away, so let's find a target!
// Start scanning and keep looking until we find a target, or get hit
do {
// Get our next scan angle, and see if we have a target
angle = nextScanAngle();
distance = scan(angle,10);
// check to see if we got hurt
gotHurt = health() < lastHealth
} while(distance == Infinity && !gotHurt);
// If we got hurt, restart the main loop so we start running away
if(gotHurt)
continue;
// If we found a target that's far away
if(distance>60) {
// Swim towards the target
swim(angle,100);
} else {
// Otherwise, stop moving (because we might have inerta)
stop();
}
// Now as long as our target is within range and we're not taking damage
while(((distance = scan(angle,10)) < 70) && health() == lastHealth) {
// FIRE!!!
cannon(angle,distance);
// If we're not close to the targetm swim at them. Otherwise stop
if(distance>5)
swim(angle);
else
stop();
}
}
}