In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Text Based Adventure Engine

The example game allows you to play a game of rock, paper, scissors, lizard, spock against Sheldon Cooper.
/**
 * Copyright paulstamp1 ( http://wonderfl.net/user/paulstamp1 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/o7VJ
 */

/**                                                          
     _____ _____ _____ __       _____ _____ _____ _____ _____ 
    |  _  |  _  |  |  |  |     |   __|_   _|  _  |     |  _  |
    |   __|     |  |  |  |__   |__   | | | |     | | | |   __|
    |__|  |__|__|_____|_____|  |_____| |_| |__|__|_|_|_|__|   
    @paulstamp
                                                       
    This project was created as part of a hack day.

    I decided to create an engine for a Text Based Adventure Game.
    Built in a web based IDE using nothing but cloud based tools.

    TOOLS:
    image editor: http://pixlr.com/editor/
    ftp upload: http://www.ftplive.com/ftp.php?
    code editor: http://wonderfl.net/

*/
package {
    import flash.external.ExternalInterface;
    import flash.system.Security;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
         
        
        public function FlashTest() {
            // write as3 code here..
            
            /**
            *
            * Use ':' in a description to allow text input
            * USe '<thing>' to enter player data           
            *
            */
            
            //setup            
            Security.allowDomain("*");
            Security.allowInsecureDomain("*");
            Security.allowDomain("http://www.paulstamp.co.uk/examples/tba");
            
            //game
            var tba:TextBasedAdventureGame = new TextBasedAdventureGame( this );
        
            //assets
            var asset_sheldon:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/sheldonFace.jpg");
            var asset_sheldonXmen:Asset = new Asset( "http://paulstamp.co.uk/examples/tba/sheldonShirt.jpg" );
            var asset_sheldonSat:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/sheldonSat.jpg" );
            var asset_smug:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/bazinga.jpg" );
            var asset_lost:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/sheldonGrump.jpg" );
            var asset_angry:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/sheldonAngry.jpg");
            var asset_spock:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/spock.jpg" );
            var asset_liveLong:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/liveLong.jpg");
            var scene1Asset:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/scene1.swf" );
            var scene2Asset:Asset = new Asset( "http://www.paulstamp.co.uk/examples/tba/scene2.swf" );
            
            //generic responses
            tba.addGenericOption( new Option( [new NavigationOperation( tba, "offerGame")], ["game"] ));  
                    
            //scenes
                //ask name
                var askName:Scene = new Scene( "askName", asset_sheldon);
                    askName.description = "Hello fellow Science lover. What is your name?:";               
                    askName.addOption( new Option( [new CaptureInputOperation( tba, "playerName", tba.playerData, new NavigationOperation( tba, "areYouReady" ) )], [] ));                                                                                                                            
                tba.addScene( askName );
                
                //are you ready
                var areYouReady:Scene = new Scene( "areYouReady", asset_sheldonSat);
                    areYouReady.description = "Greetings <playerName> did you know the X-men were named for the X in Charles Xavier. Since I am Sheldon Cooper, will you join my C-men?:";
                    areYouReady.addOption( new Option( [new NavigationOperation( tba, "likeStarTrek")], ["yes", "ok", "no"] )); 
                                                         
                tba.addScene( areYouReady );
                
                //star trek
                var likeStarTrek:Scene = new Scene( "likeStarTrek", asset_liveLong);
                    likeStarTrek.description = "Do you like Star Trek?:";
                    likeStarTrek.addOption( new Option( [new NavigationOperation( tba, "offerGame")], ["yes", "ok"] )); 
                    likeStarTrek.addOption( new Option( [new NavigationOperation( tba, "offerGame")], ["no"] )); 
                tba.addScene( likeStarTrek );
                
                //offer game
                var offerGame:Scene = new Scene( "offerGame", asset_sheldon);
                    offerGame.description = "<playerName> how about a game of Rock, Paper, Scissors, Lizard, Spock?:";
                    offerGame.addOption( new Option( [new NavigationOperation( tba, "playGame")], ["yes", "ok", "sure"] )); 
                    offerGame.addOption( new Option( [new NavigationOperation( tba, "likeStarTrek")], ["no"] ));                                                                                                                          
                tba.addScene( offerGame );
                
                //play game
                var playGame:Scene = new Scene( "playGame", asset_spock);
                    playGame.description = "good, as this is a Text Based Adventure you will have to enter either Rock, Paper, Lizard, Scissors or Spock:";               
                    playGame.addOption( new Option( [new RockPaperScissorsOperation( tba, tba.playerData )], ["rock", "paper", "lizard", "scissors", "spock"] ));                                                                                                                                              
                tba.addScene( playGame );           
                                
                //sheldon loses
                var sheldonLoses:Scene = new Scene( "sheldonLoses", asset_angry);
                    sheldonLoses.description = "Drat. <playerName> you beat my <losingMove>. Would you like to play again:";               
                    sheldonLoses.addOption( new Option( [new NavigationOperation( tba, "playGame")], ["yes", "ok"] )); 
                    sheldonLoses.addOption( new Option( [new NavigationOperation( tba, "likeStarTrek")], ["no"] ));                                                                                                                                                
                tba.addScene( sheldonLoses ); 
                
                //sheldon wins
                var sheldonWins:Scene = new Scene( "sheldonWins", asset_smug);
                    sheldonWins.description = "Bazinga I beat you <playerName> with an inspired <winningMove>. Would you like to play again:";               
                    sheldonWins.addOption( new Option( [new NavigationOperation( tba, "playGame")], ["yes", "ok"] )); 
                    sheldonWins.addOption( new Option( [new NavigationOperation( tba, "likeStarTrek")], ["no"] ));                                                                                                                                                
                tba.addScene( sheldonWins ); 
                
            //start
            tba.setScene( "askName" );
        }
    }
}
import flash.display.AVM1Movie;

import flash.system.SecurityDomain;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.events.FocusEvent;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextField;


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.events.ErrorEvent;
import flash.events.IOErrorEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.net.URLRequest;
import flash.display.Loader;
import flash.events.Event;
import flash.utils.Dictionary;
import flash.display.Scene;
import flash.events.KeyboardEvent;
import flash.events.TextEvent;
import flash.text.TextFormatAlign;
import flash.display.Sprite;
import flash.display.DisplayObjectContainer;

class TextBasedAdventureGame extends Sprite {
    
    private var _io:InputOutput;
    private var _sceneManager:SceneManager;
    private var _genericCommands:Array;
    private var _image:ImageViewer;
    private var _playerData:PlayerData;
    
    public const SIZE:uint = 465;
    
    public function TextBasedAdventureGame( parent:DisplayObjectContainer )    
    {
        parent.addChild( this );
        
        _genericCommands = [];
        
        //image
        _image = new ImageViewer( SIZE, SIZE );
        addChild( _image );        
        
        //input
        _io = new InputOutput( SIZE, SIZE, playerData );        
        _io.addEventListener( CommandEvent.COMMAND_ENTERED, handleCommand );
        addChild( _io );
        
        //scene manager
        _sceneManager = new SceneManager( _image, _io );
           
           
        _io.print( "Hello World >" );
        
        
    }
    
    public function addGenericOption( option:Option ):void
    {
        _genericCommands.push( option );
    }

    public function get playerData():PlayerData
    {
        return _playerData ||= new PlayerData();         
    }

    public function addScene( value:Scene ):void
    {
        value.tba = this;
        _sceneManager.addScene( value );
    }
    
    public function setScene( title:String ):void
    {
        _sceneManager.setScene( title );
    }

    private function handleCommand( event:CommandEvent ):void    
    {
        if( !_sceneManager.currentScene )
            return;            
        
        if( !_sceneManager.currentScene.handleCommand( event.command ))
        {
            handleGenericCommand( event );
        }        
    }
    
    public function displayFeedback( feedback:String ):void
    {
        _io.print( feedback );
    }

    private function handleGenericCommand( event:CommandEvent ):void
    {
        for each( var option:Option in _genericCommands )
        {
            if( option.hasCommand( event.command ))
            {
                 option.run( event.command ); 
                 return;  
            }           
        }        
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

import flash.display.DisplayObject;

class ImageViewer extends Sprite {
    
    public function ImageViewer( width:uint, heigt:uint )
    {
        this.graphics.beginFill( 0x000000 );
        this.graphics.drawRect( 0,0, width, height );
        this.graphics.endFill();  
    }
    
    public function displayImage( image:Loader ):void
    {
        //prevent replacing same screen
        if( this.numChildren > 0 && this.getChildAt(0)== image )
            return;
         
        if( this.numChildren > 0 )
        {
            for( var i:uint = 0; i < this.numChildren; i++)
            {
                TweenMax.to( this.getChildAt(i), 0.4, { alpha:0, x:-465, onComplete:this.getChildAt(i).parent.removeChild, onCompleteParams:[this.getChildAt(i)] });    
            }
            
            image.alpha = 0;
            image.x = 465;
            addChild( image );
            TweenMax.to( image, 0.2, { x:0, alpha:1 } );
        }
        else
        {            
            addChild( image );            
        }      
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

import flash.display.Sprite;
import com.greensock.TweenMax;

class InputOutput extends Sprite {
    
    private var _output:TextField;
    private var _input:TextField;
    private var _defaultHeight:uint = 40;    
    private var _gapAtSides:uint = 10;
    private var _gapFromBottom:uint = 20;
    private var _width:uint;
    private var _height:uint;
    private var _outputHeight:uint = 60;
    private var _inputHeight:uint = 20;
    private var _caret:Sprite;
    private var _playerData:PlayerData;
        
    public function InputOutput( width:uint, height:uint, playerData:PlayerData )
    {      
        //position at the bottom of the screen and work in negatPlayerData
        _playerData = playerData;
        _width = width;
        _height = height;
        this.y = height;
          
        var outputFormat:TextFormat = new TextFormat( "_sans", 12, 0x0eef24 );
        _output = new TextField();
        _output.defaultTextFormat = outputFormat;
        _output.type = TextFieldType.DYNAMIC;                      
        _output.width = _width - (_gapAtSides<<1);
        _output.height = _defaultHeight;
        _output.x = _gapAtSides;
        _output.y = -(_outputHeight + _gapFromBottom);
        _output.wordWrap = true;
        _output.multiline = true;
        _output.selectable = false;
        addChild( _output );
        
        var inputFormat:TextFormat = new TextFormat( "_sans", 12, 0x0eef24 );
        _input = new TextField();
        _input.defaultTextFormat = inputFormat;
        _input.type = TextFieldType.INPUT;
        _input.width = _width - (_gapAtSides<<1);
        _input.height = _defaultHeight;
        _input.addEventListener(KeyboardEvent.KEY_DOWN, onInput);
        _input.addEventListener(FocusEvent.FOCUS_IN, onFocus);
        _input.x = _gapAtSides;
        _input.y = -(_inputHeight + _gapFromBottom);
        _input.selectable = true;
        addChild( _input );
        
        _caret = new Sprite();
        _caret.graphics.beginFill( 0x009900 );
        _caret.graphics.drawRect( 0,0,4,17 );
        _caret.graphics.endFill();
        _caret.x = _gapAtSides + 10;
        addChild( _caret );
        TweenMax.to(_caret, 0.2, {tint:0x000000, repeat:-1, yoyo:true, repeatDelay:0.2});
        
        drawBackground();        
    }
    
    private function onFocus( event:FocusEvent ):void
    {
        _input.text = "";
        _caret.visible = false;
    }

    public function clearText():void
    {
        _output.text = "";
        _output.height = _defaultHeight;
        _output.y = -(60 + _gapFromBottom);
        drawBackground();     
    }
    
    public function print( message:String):void
    {   
        var lastChar:String = getLastCharInString(message);         
         
         //allow input
         _input.visible = lastChar == ":";         
        
         if( lastChar == ":" )
         {
             message = message.slice( 0, -1 );
             _input.visible = true;
             _output.text = message;                
         }
         else
         {
             _input.visible = false;             
         }
                  
         //display message
          _output.text = insertUserData(message);          
    }
    
    private function insertUserData( string:String ):String
    {
           var subs:Array = string.split( "<" );
           var pos:int;
           var sub:String;           
           var reform:String = "";
           var s:String;
           var r:String;
           
           for( var i:uint; i < subs.length; i++ )
           {
                sub = subs[i];
                pos = sub.indexOf(">");
               
               if( pos > -1 )
               {
                   
                    s = sub.substr( 0, pos );                    
                    r = _playerData.getData(s);
                    
                    sub = strReplace( sub, s+">", r );
                    subs[i] = sub;                    
               }  
               
               reform += sub;              
           }
           
           return reform;
     }
    
    private function strReplace(str:String, search:String, replace:String):String
    {
         return str.split(search).join(replace);
    }

    private function getLastCharInString( value:String):String
    {
        return value.substr(value.length-1, value.length);
    }

    
    private function drawBackground():void
    {
        this.graphics.clear();
        this.graphics.beginFill( 0x111111, 0.9 );
        this.graphics.drawRect( _gapAtSides, -(_outputHeight + _gapFromBottom), _width - (_gapAtSides<<1), _output.height );
        this.graphics.endFill();
        this.graphics.beginFill( 0x00000, 0.9 );
        this.graphics.drawRect( _gapAtSides, -(_inputHeight + _gapFromBottom), _width - (_gapAtSides<<1), _input.height );
        this.graphics.endFill();
        
        _caret.y = _input.y;
        _caret.x = _input.x + 2;
    }

    private function onInput( event:KeyboardEvent ):void
    {           
        //detect enter key
        if(event.charCode == 13)
        {                
           //infom
           this.dispatchEvent( new CommandEvent( _input.text ) );
           
           //clear field
           _input.text = "";
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class SceneManager {
    
    private var _scenes:Dictionary;
    private var _currentScene:Scene;
    private var _imageView:ImageViewer;
    private var _io:InputOutput;
    
    public function SceneManager( imageView:ImageViewer, io:InputOutput )
    {
        _io = io;
        _imageView = imageView;
        _scenes = new Dictionary();
    }
    
    public function addScene( value:Scene ):void
    {        
       _scenes[ value.title ] = value;
    }
    
    public function setScene( title:String):void
    {
        _currentScene = _scenes[ title ];
        _currentScene.displayImage( _imageView );
        _currentScene.displayDescription( _io);
    }
    
    public function get currentScene():Scene
    {
        return _currentScene;
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class Scene {
    
    public var tba:TextBasedAdventureGame
    public var description:String;
    public var title:String;
    public var image:Loader;
    
    private var _options:Array;
    private var _asset:Asset;
    
    public function Scene( title:String, asset:Asset )
    {
        this.title = title;
       
        _asset = asset;
        _options = [];
    }    
    
    public function displayImage( imageView:ImageViewer ):void
    {    
        imageView.displayImage( _asset.load() );
    }
    
    public function displayDescription( io:InputOutput):void
    {
        io.print( description );
    }

    public function addOption( option:Option ):void
    {
        _options.push( option );
    }
    
    public function handleCommand( command:String ):Boolean
    {
        var ranCommand:Boolean;
        
        for each( var option:Option in _options )
        {             
           if( option.hasCommand( command ))
           {    
               option.run( command ); 
               ranCommand = true;              
           }

        }
                
        return ranCommand;
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class Asset {
    
    public var image:Loader;    
    
    private var _imageURL:String;
    private var _imageLoaded:Boolean;
    
    public function Asset( contentURL:String )
    {
        image = new Loader();        
        image.contentLoaderInfo.addEventListener( Event.COMPLETE, imageLoadedHandler );
        image.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, imageErrorHandler );
        image.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS, imageProgressHandler );
        image.contentLoaderInfo.addEventListener( SecurityErrorEvent.SECURITY_ERROR, imageSecurityErrorHandler );
        
        _imageURL = contentURL;
       
    }    
        
    public function load():Loader
    {
        if( _imageLoaded )
            return image;
            
        var loaderContext:LoaderContext = new LoaderContext();
            loaderContext.checkPolicyFile = true;    
            loaderContext.allowCodeImport = true;
            loaderContext.applicationDomain = ApplicationDomain.currentDomain;
            //loaderContext.securityDomain = SecurityDomain.currentDomain; 
        
        image.load(new URLRequest(_imageURL), loaderContext);
        return image;
    }
    
    private function imageSecurityErrorHandler( event:SecurityErrorEvent ):void
    {
        throw new Error( "image security error" ); 
    }

    private function imageProgressHandler( event:ProgressEvent ):void
    {
        
    }
    
    private function imageErrorHandler( event:IOErrorEvent ):void
    {
        throw new Error( "Failed to load image" );    
    }
    
    private function imageLoadedHandler( event:Event ):void
    {        
        image.contentLoaderInfo.removeEventListener( Event.COMPLETE, imageLoadedHandler );
        _imageLoaded = true;
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class Option {
    
    private var _commands:Array;
    private var _operations:Array;
    private var _catchAll:Boolean;
    
    public function Option( operations:Array, commands:Array )
    {
        _catchAll = commands.length == 0;
        _operations = operations;
        _commands = commands;
    }
    
    public function addOperation( operation:IOperation ):void
    {
        _operations.push( operation );
    }

    public function addCommand( value:String ):void
    {
        _commands.push( value );
    }
    
    public function hasCommand( value:String ):Boolean
    {        
        if( _catchAll ) return true; //used to invoke operation on any command
        
        //check for command similarity
        for each( var command:String in _commands )
        {
            var sim:Number = similarity( value, command );
            
            //throw new Error( sim + "," + command + "," + value );
            if( sim > 10 )
            {
                return true;
            }
        }

        
        return _commands.lastIndexOf( value ) != -1;
    }
    
    private function similarity(p_source:String, p_target:String):Number {
        var ed:uint = editDistance(p_source, p_target);
        var maxLen:uint = Math.max(p_source.length, p_target.length);
        if (maxLen == 0) { return 100; }
        else { return (1 - ed/maxLen) * 100; }
    }
    
    private function minimum(a:uint, b:uint, c:uint):uint
    {
        return Math.min(a, Math.min(b, Math.min(c,a)));
    } 
    
    private function editDistance(p_source:String, p_target:String):uint {
            var i:uint;

            if (p_source == null) { p_source = ''; }
            if (p_target == null) { p_target = ''; }

            if (p_source == p_target) { return 0; }

            var d:Array = new Array();
            var cost:uint;
            var n:uint = p_source.length;
            var m:uint = p_target.length;
            var j:uint;

            if (n == 0) { return m; }
            if (m == 0) { return n; }

            for (i=0; i<=n; i++) { d[i] = new Array(); }
            for (i=0; i<=n; i++) { d[i][0] = i; }
            for (j=0; j<=m; j++) { d[0][j] = j; }

            for (i=1; i<=n; i++) {

                var s_i:String = p_source.charAt(i-1);
                for (j=1; j<=m; j++) {

                    var t_j:String = p_target.charAt(j-1);

                    if (s_i == t_j) { cost = 0; }
                    else { cost = 1; }

                    d[i][j] = minimum(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost);
                }
            }
            return d[n][m];
        }
    
    public function run( command:String ):void
    {    
       for each( var operation:IOperation in _operations )
        {            
            operation.execute( command );
        }
    }
 }
 
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

interface IOperation {
    
    function execute( command:String ):void;
}

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class CommandEvent extends Event{
    
    public static const COMMAND_ENTERED:String = "CommandEntered";
    
    private var _command:String;
    
    public function CommandEvent( command:String ):void
    {
        _command = command;
        super( COMMAND_ENTERED, false, false );
    }
    
    public function get command():String
    {
        return _command;
    }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class NavigationOperation implements IOperation {
    
    private var _title:String;
    private var _tba:TextBasedAdventureGame;
    
    public function NavigationOperation( tba:TextBasedAdventureGame, title:String )
    {
        _tba = tba;
        _title = title;
    }

    public function execute( command:String ):void
    {
        //do some shit
        _tba.setScene( _title );
    }

}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class FeedbackOperation implements IOperation {
    
    private var _tba:TextBasedAdventureGame;
    private var _feedback:String;
    
    public function FeedbackOperation( tba:TextBasedAdventureGame, feedback:String )
    {        
        _tba = tba;     
        _feedback = feedback;           
    }

    public function execute( command:String ):void
    {
        //do some shit
        _tba.displayFeedback( _feedback );
    }

}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class CaptureInputOperation implements IOperation {
    
    private var _tba:TextBasedAdventureGame;    
    private var _playerData:PlayerData;
    private var _storeDataWithName:String;
    private var _onComplete:IOperation;
    
    public function CaptureInputOperation( tba:TextBasedAdventureGame, storeDataWithName:String, playerData:PlayerData, onComplete:IOperation = null )
    {      
        _storeDataWithName = storeDataWithName;
        _playerData = playerData;
        _tba = tba;         
        _onComplete = onComplete;    
    }

    public function execute( command:String ):void
    {
        //command should be data to store
        _playerData.store( _storeDataWithName, command );
        
        if( _onComplete )
            _onComplete.execute( command );
     }

}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class RockPaperScissorsOperation implements IOperation {
    
    private var _tba:TextBasedAdventureGame;    
    private var _playerData:PlayerData;
    private var _storeDataWithName:String;
    private var _onComplete:IOperation;
    
    private var _results:Array;
    
    public function RockPaperScissorsOperation( tba:TextBasedAdventureGame, playerData:PlayerData )
    {      
        _playerData = playerData;
        _tba = tba; 
        
        var rock:RPS = new RPS( "rock" );
        var paper:RPS = new RPS( "paper" );
        var scissors:RPS = new RPS( "scissors" );
        var lizard:RPS = new RPS( "lizard" );
        var spock:RPS = new RPS( "spock" );
        
        rock.beats( scissors );
        rock.beats( lizard );
        paper.beats( rock );
        paper.beats( spock );
        scissors.beats( paper );
        scissors.beats( lizard );
        lizard.beats( paper );
        lizard.beats( spock );
        spock.beats( scissors );
        spock.beats( rock );
        
         
        _results = [rock, paper, scissors, lizard, spock];  
               
     }
    
    public function randomize ( a : *, b : * ) : int {
        return ( Math.random() > .5 ) ? 1 : -1;
    }

    public function execute( command:String ):void
    {   
        var command:String = command.toLowerCase(); 
        _results.sort( randomize );       
        var response:RPS;
        var entry:RPS;               
        
        for( var i:uint = 0; i < _results.length; i++)        
        {            
            var option:RPS = _results[i] as RPS;           
            
            //find option
            if( option.type == command )
            {
                entry = option;                   
            }
            else
            {
                response = option;
            }
            
            if( entry && response )
                break;
        }
        
        if( entry == null || response == null )
        {
            throw new Error( "no response" );
            return;
        }

        var didSheldonWin:Boolean = response.doYouBeat( entry );
        
        if( didSheldonWin )
        {            
            _playerData.store( "winningMove", catipaliseFirstLetter(response.type) ); 
            _tba.setScene( "sheldonWins" );
        }
        else
        {                   
            _playerData.store( "losingMove", catipaliseFirstLetter(response.type) ); 
             _tba.setScene( "sheldonLoses" );
        }


        
       
    }
    
    private function catipaliseFirstLetter($s:String):String {
        return $s.substring(0, 1).toUpperCase() + $s.substr(1, $s.length-1);
    }

    private function randomizeArray(array:Array):Array{
        var newArray:Array = new Array();
        while(array.length > 0){
            newArray.push(array.splice(Math.floor(Math.random()*array.length), 1));
        }
        return newArray;
    }

}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class RPS{
    
    public var type:String;
    
    private var _losers:Array = [];
    
    public function RPS( type:String )
    {
        this.type = type;    
    }
    
    public function beats( rps:RPS ):void
    {
        _losers.push( rps );
    }  
    
    public function doYouBeat( rps:RPS ):Boolean
    {
        for each( var option:RPS in _losers )
        {
            if( option.type == rps.type )
            {
                return true;
            }
        }
        
        return false;
    }
 
}


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class MultiOppOperation implements IOperation {
    
   private var _args:Array;
    
   public function MultiOppOperation( ...args )
   {      
        _args = args   
   }

   public function execute( command:String ):void
   {
        for each( var opp:IOperation in _args )
        {
            opp.execute( command );
        }
   }
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

class PlayerData {
    
    private var _store:Dictionary = new Dictionary();
    
    public function store( storeDataWithName:String, data:String ):void
    {
        _store[ storeDataWithName ] = data;
    }
    
    public function getData( storeDataWithName:String ):String
    {
        return _store[ storeDataWithName ];
    }
}