// 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(); } } }