fox/duck problem

by wh0
A duck is in the middle of a circular pond.
A fox is waiting along the edge, ready for an easy meal.
The fox can run four times as fast as the duck can swim.
If the duck can reach the shore without running into the
fox, then it can fly away.

You have to play as the fox (you can't win).
The simulation starts when you activate the movie.
Use A and D or arrow keys to move.
♥0 | Line 109 | Modified 2010-02-21 06:21:38 | MIT License
play

ActionScript3 source code

/**
 * Copyright wh0 ( http://wonderfl.net/user/wh0 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/88Iy
 */

/*
A duck is in the middle of a circular pond.
A fox is waiting along the edge, ready for an easy meal.
The fox can run four times as fast as the duck can swim.
If the duck can reach the shore without running into the
fox, then it can fly away.

You have to play as the fox (you can't win).
The simulation starts when you activate the movie.
Use A and D or arrow keys to move.
*/

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.display.Shape;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    public class DuckProblem extends Sprite {
        
        private const m:Number = 465 / 2;
        private const r:Number = 200;
        private const fv:Number = 1. / 256;
        private const dv:Number = Math.PI * fv / 4;
        private const dc:Number = Math.cos(Math.PI * fv);
        private const ds:Number = Math.sin(Math.PI * fv);
        
        private var dr:Number = 0;
        private var dt:Number = -0.5;
        private var ft:Number = -0.5;
        
        private var fl:Boolean = false;
        private var fr:Boolean = false;
        
        private var d:Shape;
        private var f:Shape;
        	
        public function DuckProblem() {
            Wonderfl.disable_capture();
            
            graphics.beginFill(0x0000ff, 0.1);
            graphics.drawCircle(m, m, r);
            graphics.endFill();
            
            d = new Shape();
            d.graphics.beginFill(0xffff00);
            d.graphics.drawCircle(0, 0, 3);
            d.graphics.endFill();
            d.x = m;
            d.y = m;
            addChild(d);
            
            f = new Shape();
            f.graphics.beginFill(0x805000);
            f.graphics.drawCircle(0, 0, 3);
            f.graphics.endFill();
            f.x = m;
            f.y = m - r;
            addChild(f);
            
            stage.addEventListener(Event.ACTIVATE, start);
        }
        
        private function start(e:Event):void {
            stage.removeEventListener(Event.ACTIVATE, start);
            graphics.lineStyle(1, 0x000000, 0.5);
            graphics.moveTo(d.x, d.y);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, kd);
            stage.addEventListener(KeyboardEvent.KEY_UP, ku);
            stage.addEventListener(Event.ENTER_FRAME, tick);
        }
        
        private function kd(e:KeyboardEvent):void {
            switch (e.keyCode) {
            case Keyboard.LEFT:
            case 'A':
                fl = true;
                break;
            case Keyboard.RIGHT:
            case 'D':
                fr = true;
                break;
            }
        }
        
        private function ku(e:KeyboardEvent):void {
            switch (e.keyCode) {
            case Keyboard.LEFT:
            case 'A':
                fl = false;
                break;
            case Keyboard.RIGHT:
            case 'D':
                fr = false;
                break;
            }
        }
        
        private function tick(e:Event):void {
            fox();
            duck();
            
            f.x = m + r * Math.cos(ft * Math.PI);
            f.y = m + r * Math.sin(ft * Math.PI);
            d.x = m - r * dr * Math.cos(dt * Math.PI);
            d.y = m - r * dr * Math.sin(dt * Math.PI);
            graphics.lineTo(d.x, d.y);
            
            if (dr > 1) {
                stage.removeEventListener(Event.ENTER_FRAME, tick);
                stage.removeEventListener(KeyboardEvent.KEY_DOWN, kd);
                stage.removeEventListener(KeyboardEvent.KEY_UP, ku);
                fl = fr = false;
            }
        }
        
        private function fox():void {
            if (fl && !fr)
                ft -= fv;
            else if (fr && !fl)
                ft += fv;
            if (ft >= 1)
                ft -= 2;
            else if (ft < -1)
                ft += 2;
        }
        
        private function duck():void {
            if (dr < 1. / 4 && fl != fr) {
                dt = ft;
                var s:Number = ds * dr;
                dr = dr * dc + Math.sqrt(dv * dv - s * s);
            } else {
                dr += dv;
            }
        }
        
    }
}