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

Zone of Cooperation

Reference - <Zones of Cooperation in Demographic Prisoner's Dilemma, Joshua M. Epstein>
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.8.8629&rep=rep1&type=pdf

Everyone in this population is one of two types - cooperator(Green color) or defector(Red color). Agents move and play game, and payoffs accumulate. If accumulated payoff exceed some threshold, agents clone offspring of the same strategy(C-> C, D-> D). Agents have life(20 frames).

* * * Reward Table (Row Player, Column Player)
       C          D
C    (R, R)   (S, T)
D    (T, S)    (P, P)
Get Adobe Flash player
by greentec 08 Nov 2015
/**
 * Copyright greentec ( http://wonderfl.net/user/greentec )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/UUPT
 */

package {
    import flash.display.Sprite;
    import com.bit101.components.Label;
    import com.bit101.components.NumericStepper;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.geom.Rectangle;
    public class FlashTest extends Sprite {
        
        public var bitmap:Bitmap;
        public var bitmapData:BitmapData;
        
        public var gridWidth:int = 13;
        public var gridHeight:int = 13;
        public var gridWidthNum:int = 30;
        public var gridHeightNum:int = 30;
        
        public var indentX:int;
        public var indentY:int;
        
        public var colorObject:Object = {
            "C"    :    0x1EC266,
            "D"    :    0x831322
        }
        
        public var playerArray:Array;
        public var population:Vector.<Vector.<Player>> = new Vector.<Vector.<Player>>(gridWidthNum);
        public var grid:Vector.<Vector.<Boolean>> = new Vector.<Vector.<Boolean>>(gridWidthNum);
        
        public var rewardObject:Object = {
            "T"    :    -6,
            "R"    :    -5,
            "P"    :    2,
            "S"    :    6
        }
        
        public var initialLife:int = 25;
        public var reproduceThreshold:int = 10;
        
        public var statsLabel:Label;
        
        public function FlashTest() {
            // write as3 code here..
            //initialize graphics
            var background:BitmapData = new BitmapData(465, 465, false, 0x292929);
            addChild(new Bitmap(background));
            
            bitmapData = new BitmapData(465, 465, true, 0xff292929);
            bitmap = new Bitmap(bitmapData);
            addChild(bitmap);
            
            //grid
            var grid:Shape = new Shape();
            grid.graphics.lineStyle(0, 0xcccccc, 0.5);
            
            var i:int;
            for (i = 0; i <= gridWidthNum; i += 1)
            {
                grid.graphics.moveTo(0, i * gridHeight);
                grid.graphics.lineTo(gridWidth * gridWidthNum, i * gridHeight);
            }
            
            for (i = 0; i <= gridHeightNum; i += 1)
            {
                grid.graphics.moveTo(i * gridWidth, 0);
                grid.graphics.lineTo(i * gridWidth, gridHeight * gridHeightNum);
            }
            
            grid.x = (465 - gridWidth * gridWidthNum) / 2;
            grid.y = (465 - gridHeight * gridHeightNum) / 2;
            addChild(grid);
            
            indentX = (465 - gridWidth * gridWidthNum) / 2;
            indentY = (465 - gridHeight * gridHeightNum) / 2;
            
            makeInitialPopulation();
            drawGraphics();
            
            //UI
            var label:Label;
            var numericStepper:NumericStepper;
            
            label = new Label(this, 10, 440, "T");
            numericStepper = new NumericStepper(this, 20, 440, onRewardChanged);
            numericStepper.name = "T";
            numericStepper.value = parseInt(rewardObject.T);
            numericStepper.width = 60;
            
            label = new Label(this, 130, 440, "R");
            numericStepper = new NumericStepper(this, 140, 440, onRewardChanged);
            numericStepper.name = "R";
            numericStepper.value = parseInt(rewardObject.R);
            numericStepper.width = 60;
            
            label = new Label(this, 250, 440, "P");
            numericStepper = new NumericStepper(this, 260, 440, onRewardChanged);
            numericStepper.name = "P";
            numericStepper.value = parseInt(rewardObject.P);
            numericStepper.width = 60;
            
            label = new Label(this, 370, 440, "S");
            numericStepper = new NumericStepper(this, 380, 440, onRewardChanged);
            numericStepper.name = "S";
            numericStepper.value = parseInt(rewardObject.S);
            numericStepper.width = 60;
            
            statsLabel = new Label(this, 280, 5, "");
            
            addEventListener(Event.ENTER_FRAME, onGameLoop);
        }
        
        private function onRewardChanged(e:Event):void
        {
            rewardObject[e.target.name] = e.target.value;
        }
        
        private function onGameLoop(e:Event = null):void
        {
            
            makeGame();
            makeChild();
            makeMove();
            drawGraphics();
            
            //debugShape.graphics.clear();
            //debugShape.graphics.lineStyle(0, 0xffffff);
            
            var Ccount:int = 0;
            var Dcount:int = 0;
            var i:int;
            var len:int = playerArray.length;
            var player:Player;
            
            for (i = 0; i < len; i += 1)
            {
                player = playerArray[i];
                if (player.type == "C")
                {
                    Ccount += 1;
                }
                else if (player.type == "D")
                {
                    Dcount += 1;
                }
            }
            
            statsLabel.text = "Cooperate Player :\t" + String(Ccount) + " (" + String(int(Ccount / (Ccount + Dcount) * 1000) / 10) + " %)" + "\nDefect Player :\t\t" + String(Dcount) + " (" + String(int(Dcount / (Ccount + Dcount) * 1000) / 10) + " %)";
            
        }
        
        private function makeChild():void
        {
            var i:int;
            var len:int = playerArray.length;
            var player:Player;
            var childPlayer:Player;
            var dir:String;
            var newX:int;
            var newY:int;
            
            for (i = 0; i < len; i += 1)
            {
                player = playerArray[i];
                if (player.wealth >= reproduceThreshold)
                {
                    dir = findNeighbor(player, false); //find empty cell
                    
                    if (dir != "")
                    {
                        dir = dir.substr(int(Math.random() * dir.length), 1);
                        
                        switch(dir)
                        {
                            case "E":
                                newX = (player._x + 1) % gridWidthNum;
                                newY = player._y;
                                break;
                                
                            case "W":
                                newX = (player._x - 1 + gridWidthNum) % gridWidthNum;
                                newY = player._y;
                                break;
                                
                            case "S":
                                newX = player._x;
                                newY = (player._y + 1) % gridHeightNum;
                                break;
                                
                            case "N":
                                newX = player._x;
                                newY = (player._y - 1 + gridHeightNum) % gridHeightNum;
                                break;
                        }
                        
                        childPlayer = new Player(newX, newY, initialLife, player.type, player.wealth / 2);
                        population[newX][newY] = childPlayer;
                        grid[newX][newY] = true;
                        playerArray.push(childPlayer);
                        
                        player.wealth /= 2;
                        
                        
                    }
                }
                
                
            }
        }
        
        private function makeGame():void
        {
            var i:int;
            var j:int;
            var len:int = playerArray.length;
            var player:Player;
            var player2:Player;
            var dir:String;
            
            for (i = 0; i < len; i += 1)
            {
                
                player = playerArray[i];
                dir = findNeighbor(player, true); //find neighbor - occupied cell
                
                if (dir != "")
                {
                    dir = dir.substr(int(Math.random() * dir.length), 1);
                    
                    switch(dir)
                    {
                        case "E":
                            player2 = population[(player._x + 1) % gridWidthNum][player._y];
                            
                            break;
                            
                        case "W":
                            player2 = population[(player._x - 1 + gridWidthNum) % gridWidthNum][player._y];
                            
                            break;
                            
                        case "S":
                            player2 = population[player._x][(player._y + 1) % gridHeightNum];
                            
                            break;
                            
                        case "N":
                            player2 = population[player._x][(player._y - 1 + gridHeightNum) % gridHeightNum];
                            
                            break;
                            
                    }
                    
                    if (player.type == "C" && player2.type == "C")
                    {
                        player.wealth += rewardObject.P;
                        player2.wealth += rewardObject.P;
                    }
                    else if (player.type == "D" && player2.type == "C")
                    {
                        player.wealth += rewardObject.S;
                        player2.wealth += rewardObject.T;
                    }
                    else if (player.type == "C" && player2.type == "D")
                    {
                        player.wealth += rewardObject.T;
                        player2.wealth += rewardObject.S;
                    }
                    else if (player.type == "D" && player2.type == "D")
                    {
                        player.wealth += rewardObject.R;
                        player2.wealth += rewardObject.R;
                    }
                }
                
            }
            
        }
        
        private function findNeighbor(player:Player, occupied:Boolean):String
        {
            var dir:String;
            
            dir = "";
                
            if (grid[(player._x + 1) % gridWidthNum][player._y] == occupied)
            {
                dir += "E";
            }
            if (grid[(player._x - 1 + gridWidthNum) % gridWidthNum][player._y] == occupied)
            {
                dir += "W";
            }
            if (grid[player._x][(player._y + 1) % gridHeightNum] == occupied)
            {
                dir += "S";
            }
            if (grid[player._x][(player._y - 1 + gridHeightNum) % gridHeightNum] == occupied)
            {
                dir += "N";
            }
            
            return dir;
            
        }
        
        private function makeMove():void
        {
            var i:int;
            var j:int;
            var len:int = playerArray.length;
            var player:Player;
            var dir:String;
            var randDir:String;
            
            for (i = len - 1; i > -1; i -= 1)
            {
                
                player = playerArray[i];
                player.life -= 1;
                
                if (player.life <= 0)
                {
                    playerArray.splice(i, 1);
                    grid[player._x][player._y] = false;
                    population[player._x][player._y] = null;
                    player = null;
                    
                    continue;
                }
                
                dir = findNeighbor(player, false); //find empty neighbor cell - to move
                if (dir != "")
                {
                    
                    randDir = dir.substr(int(Math.random() * dir.length), 1);
                    
                    
                    switch(randDir)
                    {
                        case "E":
                            grid[player._x][player._y] = false;
                            population[(player._x + 1) % gridWidthNum][player._y] = player;
                            population[player._x][player._y] = null;
                            player._x = (player._x + 1) % gridWidthNum;
                            
                            
                            grid[player._x][player._y] = true;
                            //population[player._x][player._y] = player;
                            
                            break;
                            
                        case "W":
                            grid[player._x][player._y] = false;
                            population[(player._x - 1 + gridWidthNum) % gridWidthNum][player._y] = player;
                            population[player._x][player._y] = null;
                            player._x = (player._x - 1 + gridWidthNum) % gridWidthNum;
                            
                            
                            grid[player._x][player._y] = true;
                            //population[player._x][player._y] = player;
                            
                            break;
                            
                        case "S":
                            grid[player._x][player._y] = false;
                            population[player._x][(player._y + 1) % gridHeightNum] = player;
                            population[player._x][player._y] = null;
                            player._y = (player._y + 1) % gridHeightNum;
                            
                            
                            grid[player._x][player._y] = true;
                            
                            
                            break;
                            
                        case "N":
                            grid[player._x][player._y] = false;
                            population[player._x][(player._y - 1 + gridHeightNum) % gridHeightNum] = player;
                            population[player._x][player._y] = null;
                            player._y = (player._y - 1 + gridHeightNum) % gridHeightNum;
                            
                            
                            grid[player._x][player._y] = true;
                            
                            
                            break;
                            
                    }
                }
                
                
            }
            
            
        }
        
        private function makeInitialPopulation():void
        {
            var initialCooperateNum:int = 50;
            var initialDefectNum:int = 50;
            
            var i:int;
            var j:int;
            var player:Player;
            
            //initialize Grid
            for (i = 0; i < gridWidthNum; i += 1)
            {
                grid[i] = new Vector.<Boolean>(gridHeightNum);
                
                for (j = 0; j < gridHeightNum; j += 1)
                {
                    grid[i][j] = false;
                }
                
            }
            
            for (i = 0; i < gridWidthNum; i += 1)
            {
                population[i] = new Vector.<Player>(gridHeightNum);
                
                for (j = 0; j < gridHeightNum; j += 1)
                {
                    population[i][j] = null;
                }
            }
            
            //population = [];
            var initialPopulationIndex:Array = printRandomNumber(gridWidthNum * gridHeightNum, initialCooperateNum + initialDefectNum);
            playerArray = [];
            
            for (i = 0; i < initialCooperateNum; i += 1)
            {
                player = new Player(initialPopulationIndex[i] % gridWidthNum, int(initialPopulationIndex[i] / gridWidthNum), initialLife, "C");
                population[initialPopulationIndex[i] % gridWidthNum][int(initialPopulationIndex[i] / gridWidthNum)] = player;
                
                grid[initialPopulationIndex[i] % gridWidthNum][int(initialPopulationIndex[i] / gridWidthNum)] = true;
                playerArray.push(player);
            }
            
            for (i = initialDefectNum; i < initialCooperateNum + initialDefectNum; i += 1)
            {
                player = new Player(initialPopulationIndex[i] % gridWidthNum, int(initialPopulationIndex[i] / gridWidthNum), initialLife, "D");
                population[initialPopulationIndex[i] % gridWidthNum][int(initialPopulationIndex[i] / gridWidthNum)] = player;
                
                grid[initialPopulationIndex[i] % gridWidthNum][int(initialPopulationIndex[i] / gridWidthNum)] = true;
                playerArray.push(player);
            }
            
            
            
        }
        
        private function drawGraphics():void
        {
            var i:int;
            var j:int;
            var len:int = playerArray.length;
            var player:Player;
            var _alpha:int;
            
            bitmapData.fillRect(bitmapData.rect, 0xff292929);
            
            for (i = 0; i < len; i += 1)
            {
                
                player = playerArray[i];
                _alpha = Math.min((player.wealth + 30) / 60 * 255, 255);
                
                
                bitmapData.fillRect(
                    new Rectangle(player._x * gridWidth + indentX, player._y * gridHeight + indentY, gridWidth, gridHeight), 
                    _alpha << 24 | colorObject[player.type]
                );
                
                
                
            }
            
            
        }
        
        private function printRandomNumber(n:int, k:int) : Array
        {
            var original:Array=[];
            var result:Array=[];
            var i:int;
            var randInt:int;
            var temp:Object;
            
            for(i=0;i<n;i+=1)
            {
                original.push(i);
            }
            
            for(i=0;i<k;i+=1)
            {
                randInt = Math.random() * (n-i) + i;
                temp = original[i];
                original[i] = original[randInt];
                original[randInt] = temp;
                result.push(original[i]);
            }
            
            return result;
        }
    }
}

Class  
{
    /**
     * ...
     * @author ypc
     */
    class Player 
    {
        public var life:int;
        public var _x:int;
        public var _y:int;
        public var type:String;
        public var wealth:int;
        
        public function Player(_x:int, _y:int, life:int, type:String, wealth:int = 0) 
        {
            this._x = _x;
            this._y = _y;
            this.life = life;
            this.type = type;
            this.wealth = wealth;
        }
        
    }

}