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

家畜伝染病のシミュレーション

家畜伝染病のシミュレーション
左クリックで、殺処分
SHIFTキー+左クリックで、消毒薬を散布
消毒薬は一日毎に補充されます。感染拡大を食い止めてください
感染拡大を防ぐためには、初動の対処が必要不可欠
赤:発症
黄:潜伏期間
緑:健康
灰:殺処分
参考:口蹄疫と消毒薬
http://d.hatena.ne.jp/Yosyan/20100510
解説など:
http://game.g.hatena.ne.jp/Nao_u/20100512
Get Adobe Flash player
by Nao_u 16 May 2010
  • Forked from Nao_u's 伝染病のシミュレーション
  • Diff: 663
  • Related works: 1
  • Talk

    hacker_n8a1584h at 12 May 2010 12:50
    興ざめすること言って申し訳ないけど、被害者には配慮すべきと思いますよ。
    Nao_u at 13 May 2010 05:32
    初手で迅速な対処を行うか、拡大後であっても十分な機材と人員を適切に活用すれば(膨大な労力は必要ですが)、感染を抑え込むことができようには意識して調整してありますが、実際に被害者の方がおられる問題でもありますので配慮が足りず不快に思われた方には心からお詫び申し上げます。一日でも早い収束を願うとともに、その後も適切な支援が行われることに期待したいです。

    Tags

    Embed
//
// 家畜伝染病のシミュレーション
//
//
// 左クリックで、殺処分
// SHIFTキー+左クリックで、消毒薬を散布
//
// 消毒薬は一日毎に補充されます。感染拡大を食い止めてください
//
// 感染拡大を防ぐためには、初動の対処が必要不可欠
//
//
// 赤:発症
// 黄:潜伏期間
// 緑:健康
// 灰:殺処分
//
// 参考:口蹄疫と消毒薬
// http://d.hatena.ne.jp/Yosyan/20100510
//
// 解説など:
// http://game.g.hatena.ne.jp/Nao_u/20100512

package {      
    import flash.display.Sprite;      
    import flash.events.*;      
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="5")]       
         
    public class FlashTest extends Sprite {      
        public function FlashTest() {      
            Main = this;      
            initialize();      
            stage.addEventListener(Event.ENTER_FRAME,update);       
            stage.addEventListener(MouseEvent.MOUSE_DOWN,  viewClickEvent);    
            stage.addEventListener(KeyboardEvent.KEY_UP,   keyCheckUp); 
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyCheckDown); 
        }      
    }      
}  

var kansen:int  = 80;       // 感染率(%)
var dokusei:int = 1;       // 毒性の強さ
var senpuku:int = 2;       // 潜伏期間
var hassyou:int = 70;        // 発症時間
var meneki:int  = 5;       // 免疫期間

var OcrockLength:Number = 5;            // 一時間の長さ
var DayLength:Number = OcrockLength*24; // 一日の長さ
var moveRate:Number = 0.25; // 移動の自由度
var kakuri:Number = 0;

var MoveRateAry:Array = new Array();

import flash.display.Bitmap;  
import flash.display.BitmapData;  
import flash.display.Sprite;       
import flash.events.* 
import flash.text.TextField;      
import flash.geom.*; 
import flash.utils.getTimer; 
var Main:Sprite;      
var SCREEN_W:Number = 465; 
var SCREEN_H:Number = 465; 
var View: Bitmap;  
var BmpData: BitmapData;  
var BgColor:int = 0x101010;
var WallColor:int = 0xf08080;
var WallColor2:int = 0x807070;

var ColGreen:int  = 0x408040;
var ColYellow:int = 0xffff40;
var ColRed0:int    = 0xff6060;
var ColRed1:int    = 0xff4040;
var ColBlue:int   = 0x2070a0;
var ColGray:int   = 0x404040;

var BITMAP_W:int = 465; 
var BITMAP_H:int = 384; 

var AgentAry:Vector.<Agent> = new Vector.<Agent>;
var CarAry:Vector.<Car> = new Vector.<Car>;
var FarmAry:Vector.<Farm> = new Vector.<Farm>;
var DisinfectantAry:Vector.<Disinfectant> = new Vector.<Disinfectant>;
var Text0:TextField = new TextField();
var Text1:TextField = new TextField();
var Text2:TextField = new TextField();
var Time:int = 0;
var StateAry:Array = new Array();

var ResetButton:Button;
var KakuriButton:Button;
var Idou:TextField = new TextField();
var Kokkyou:TextField = new TextField();
var IdouType:int = 1;
var KokkyouType:int = 2;
var Syoudoku:int;
var SyoudokuPlus:Number;

var Tex:ProcTex;

var Month:int;
var Day:int;
var DaysTable:Array = [0, 31, 28, 31, 30, 31, 30, 31, 30, 31, 31, 30, 31];

function initialize():void{      

    MoveRateAry.push( 0.05 );
    MoveRateAry.push( 0.25 );
    MoveRateAry.push( 0.55 );
    MoveRateAry.push( 0.85 );

    BmpData = new BitmapData(BITMAP_W, BITMAP_H, false, 0xffffff);  
    View = new Bitmap(BmpData);  
    View.scaleX = 1.0; 
    View.scaleY = 1.0; 
    Main.addChild(View);       

    Tex = new ProcTex( BITMAP_W, BITMAP_H,BmpData ); 
    Tex.Bmp.x = 0; 
    Tex.Bmp.y = 0; 

     Text0.x = 10;
    Text0.y = 386;
    Text0.defaultTextFormat = new TextFormat( "AXIS Std R", 13, 0, false );
    Main.addChild(Text0); 
    
    Text1.x = 89;
    Text1.y = 388;
    Text1.width = 384;
    Text1.defaultTextFormat = new TextFormat( "AXIS Std R", 10, 0, false );
    Main.addChild(Text1); 

    Text2.x = 20;
    Text2.y = 406;
    Text2.defaultTextFormat = new TextFormat( "AXIS Std R", 13, 0, false );
    Main.addChild(Text2); 

    reset();

   createResetButton();
    createKakuriButton();

} 

function viewClickEvent(event:MouseEvent):void{
    var mx:Number = Main.stage.mouseX;    
    var my:Number = Main.stage.mouseY;    
    if( KeyData & KEY_SHIFT ){
        if( Syoudoku > 0 ){
            Syoudoku--;
            new Disinfectant( mx,my,  16, 128 );  
        }
    }else{
        killAgent(mx,my);
    }
}

function createAgent():void{
    new Farm(  35, 50,  50, 50,  20, 0.05 );
//    new Farm(  35, 50,  50, 50,  80, 0.95 );
    new Farm( 150, 50,  50, 50, 256, 0 );
    new Farm( 250, 50,  70, 50,  14, 0.0 );
    new Farm( 350, 50,  75, 45,  10, 0.0 );

    new Farm(  30,110, 110, 60,  16, 0 );
    new Farm( 190,110,  25, 25,  64, 0.0 );
    new Farm( 290,110,  50,120,  50, 0.0 );
    new Farm( 390,110,  50, 50, 127, 0 );

    new Farm(  50,190,  40, 80,  16, 0 );
    new Farm( 110,220,  30, 50, 160, 0 );
    new Farm(  90,280,  50, 50,  40, 0 );
    new Farm( 150,150,  80, 80, 128, 0.0 );
    new Farm( 290,250, 150,60, 100, 0.01 );

    new Farm( 150,260,  65, 30,  20, 0 );
    new Farm( 270,320,  25, 40,  90, 0 );
    new Farm( 220,250,  35, 80,  20, 0 );
    new Farm(  20,300,  45, 50,  30, 0 );
    new Farm( 235,160,  45, 20,  30, 0 );
    new Farm( 380,190,  25, 30,  30, 0 );
    new Farm( 310,345,  45, 18,  10, 0 );
    new Farm( 395,340,  35, 18,  80, 0 );

    for( var i:int=0; i<5; i++ ){
        new Car( 0,50, 50,100 );
        new Car( 100,0, 200,200 );
        new Car( 100,100, 300,300 );
        new Car( 100,100, 300,300 );
    }
/*    new Car( 0,0, 100,100 );
    new Car( 0,0, 100,100 );
    new Car( 0,0, 100,100 );
    new Car( 0,0, 100,100 );
    new Car( 0,0, 100,100 );
*/
}

function createKakuriButton():void{
    KakuriButton = new Button(64, 18, 8, "人の移動 通常", 10);
    KakuriButton.x = 468-120
    KakuriButton.y = 468-52
    KakuriButton.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void{
            if( kakuri == 0.0 ) {
                KakuriButton.setLabel("人の移動 制限");
                kakuri = 1.0;
            }else{
                KakuriButton.setLabel("人の移動 通常");
                kakuri = 0.0;
            }
        }
    ); 
    Main.addChild(KakuriButton);
}

function reset():void{
    AgentAry = new Vector.<Agent>;
    CarAry   = new Vector.<Car>;
    FarmAry  = new Vector.<Farm>;
    DisinfectantAry = new Vector.<Disinfectant>;

    Tex.clear();
    clearBmp();    
    createAgent();

    Month = 4;
    Day   = 20;
    Time  = 0;

    Syoudoku = 1;
    SyoudokuPlus = 1;

    kakuri = 0.0;
//    KakuriButton.setLabel("人の移動 通常");
}

function createResetButton():void{
    ResetButton = new Button(64, 18, 8, "Reset", 16);
    ResetButton.x = 468-120;
    ResetButton.y = 468-22;
    ResetButton.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void{reset();Time=0;}
    ); 
    Main.addChild(ResetButton);
}

function updateTex():void{
    Tex.draw(); 
}

function update(e :Event):void{      

    var num:int = 0;
    for( var i:int=0; i<5; i++ ) StateAry[i] = 0;

    for each( var agent:Agent in AgentAry )  { agent.update(); num++; }
    for each( var car:Car  in CarAry ) car.update();
    for each( var dis:Disinfectant in DisinfectantAry ) dis.update();
    clearBmp();    

    for each( dis in DisinfectantAry ) dis.draw();
    for each( var farm:Farm  in FarmAry ) farm.draw();
    for each( agent  in AgentAry ) agent.draw();
    for each( var cr:Car  in CarAry ) cr.draw();
    updateTex();

    Time++;
    var ocrock:int = Time/OcrockLength;
    if( ocrock == 24 ) {
        ocrock = 0;
        Time=0;
        Day++;

        Syoudoku += SyoudokuPlus;
        SyoudokuPlus += 0.75;
    }
    if( Day > DaysTable[Month] ) {
        Day = 1;
        Month++;
        if( Month == 13 ) Month = 1;
    }
    var n0:String = (StateAry[0]*10).toFixed(0);
    var n1:String = (StateAry[1]*10).toFixed(0);
    var n2:String = (StateAry[2]*10).toFixed(0);
//    var n3:String = (StateAry[3]*10).toFixed(0);
    var n4:String = (StateAry[4]*10).toFixed(0);
    Text0.text = Month+"月"+ Day +"日 "+ocrock+"時";
    Text1.htmlText = 
        "<font color='#006000'>健康</font>: "+n0+"   " +
        "<font color='#b0b000'>潜伏</font>: "+n1+"   " +
        "<font color='#b00000'>発症</font>: "+n2+"   " +
        "<font color='#303030'>殺処分</font>: "+n4+"   " ;
            
    Text2.text = "消毒薬:" + Syoudoku;
}

function darwWall( sx:int, sy:int, w:int, h:int, col:int ):void{
    var ex:int = sx+w;
    var ey:int = sy+h;
    for( var x:int=sx; x<sx+w; x++){
        BmpData.setPixel(x, sy, col);  
        BmpData.setPixel(x, ey, col);  
    }
    for( var y:int=sy; y<sy+h; y++){
        BmpData.setPixel(sx, y, col);  
        BmpData.setPixel(ex, y, col);  
    }
}

function darwCircle( sx:int, sy:int, r:int, col:int ):void{
    var x:Number, y:Number;
    for( var i:Number=0; i<3.14*2; i+=3.14/64 ){
        x = sx + r*Math.sin(i);
        y = sy + r*Math.cos(i);
        BmpData.setPixel(x, y, col);  
    }

}

function clearBmp():void{
    var col:int = 0xc0c0c0;
    var x:int;
    var y:int;

    for( x=0; x<BITMAP_W; x++){
        for( y=0; y<BITMAP_H; y++){
           BmpData.setPixel(x, y, BgColor);  
        }
    }
}


class Car{  
    public var X:Number;
    public var Y:Number;
    public var Sx:Number;
    public var Sy:Number;
    public var Ex:Number;
    public var Ey:Number;
    public var SpdX:Number;
    public var SpdY:Number;
     public var CountDown:int = 0;
    public var Poison:Number = 0;
    public function Car( x:Number, y:Number, ex:Number, ey:Number ){  
        do{
            X = x + ex*Math.random();
            Y = y + ey*Math.random();
        } while( BmpData.getPixel(X, Y) != BgColor );

        CarAry.push(this);
    }

    public function update():void{
        {
          var rate:Number = 1.5;
            var nomove:Boolean = false;
            if( kakuri == 1.0 ) { rate *= 0.1; Poison = 0; }
            if( CountDown <= 0 ){
                CountDown = 30;
                var rad:Number = Math.random()*3.14*2;
                SpdX = rate * Math.sin(rad);
                SpdY = rate * Math.cos(rad);
            }else{
                CountDown--;
            }
            var bgCol:int = BmpData.getPixel(X+SpdX, Y+SpdY);
            if( bgCol != WallColor )
            {
                X += SpdX;
                Y += SpdY;
                if( X < 2 ){ X = 2; SpdX*=-1; nomove = true; }
                if( X > BITMAP_W-4 ){ X = BITMAP_W-4; SpdX*=-1; nomove = true; }

                if( Y < 2 ){  Y = 2; SpdY*=-1;  nomove = true; }
                if( Y > BITMAP_H-4 ){ Y = BITMAP_H-4; SpdY*=-1;nomove = true; }
            }else{
                SpdX*=-1;
                SpdY*=-1;
                nomove = true;
            }
            if( nomove == true ) Poison *= 0.1;

        }
        var pow:Number = 0.5 * Tex.getPower(X, Y);
        if( Poison < pow ) Poison = pow;
        if( kakuri == 1.0 ) { Poison = 0; }
        Tex.addPower( X, Y, Poison*0.2 );
        Poison *= 0.99;
        if( Poison > 1 ) Poison = 1;
        if( Poison < 0 ) Poison = 0;
    }

    public function draw():void{
        var col0:int, col1:int;
        col1 = ColBlue;
        BmpData.setPixel(X,   Y, col1);  
        setPixel(X+1, Y, col1);  
        setPixel(X,   Y+1, col1);  
        setPixel(X+1, Y+1, col1);  
    }
}

class Agent{  
    public var X:Number;
    public var Y:Number;
    public var Hp:int, HpMax:int;
    public var Status:int = 0;    // 0:健康 1:潜伏期間 2:発病
     public var CountDown:int = 0;
    public var Poison:Number = 0;
    public function Agent( x:Number, y:Number, px:Number, py:Number, status:int ){  
        do{
            X = x + px*Math.random();
            Y = y + py*Math.random();
        } while( BmpData.getPixel(X, Y) != BgColor );

        Hp = 15000 + Math.random() * 25000;
        AgentAry.push(this);
        Status = status;
        if( Status == 1 ){
            Tex.addPower( X,   Y,   0.7 );
            Tex.addPower( X-3, Y,   0.7 );
            Tex.addPower( X+3, Y,   0.7 );
            Tex.addPower( X,   Y+3, 0.7 );
            Tex.addPower( X,   Y-3, 0.7 );
        }
    }

    public function update():void{
        StateAry[Status]++;

        if( Status != 4 ){
            var sx:Number = moveRate * (Math.random()*5 - 2.5);
            var sy:Number = moveRate * (Math.random()*5 - 2.5);
            var bgCol:int = BmpData.getPixel(X+sx, Y+sy);
            if( bgCol != WallColor && !(Status == 2 && KokkyouType == 1 && bgCol == WallColor2) ){
                X += sx;
                Y += sy;
                if( X < 2 ) X = 2; 
                if( X > BITMAP_W-4 ) X = BITMAP_W-4; 
                if( Y < 2 ) Y = 2; 
                if( Y > BITMAP_H-4 ) Y = BITMAP_H-4; 
            }  
        }
        if( Status == 0 ){
            if( Hp < HpMax ) {
                Hp+=3;
            }
            Poison += Tex.getPower(X+sx, Y+sy);
            Poison -= 0.0005;
            if( Poison < 0 ) Poison = 0;
            if( Poison > 5.0 ){
                if( Math.random()*100 < kansen ) {    // 感染力
                    Status = 1;
                    CountDown = senpuku * DayLength;    // 潜伏期間
                }
            }  
        }
        if( Status == 1 ){
            CountDown--;
            if( CountDown <= 0 ) {
                CountDown = hassyou * DayLength;    // 発症時間
                   Status = 2;
                Tex.addPower( X, Y, 0.5 );
            }
        }
        if( Status == 2 ){
           Tex.addPower( X, Y, 0.030 );
             Hp-= dokusei * 10;              // 毒性の強さ
            CountDown--;
            if( CountDown <= 0 ) {
                CountDown = meneki * DayLength;    // 免疫期間
                Status = 3;
            }
            if( Hp <= 0 ) {
                Status = 4;
            }
        }
        if( Status == 3 ){
            CountDown--;
            if( CountDown <= 0 ) {
                CountDown = 0;    // 
                Status = 0;
            }
        }

    }

    public function getColYellowRatio():int{
         var max:Number = senpuku * DayLength;
         var ratio:Number = CountDown / max;
         ratio = 1 - ratio;
         ratio = ratio*ratio*ratio;
         ratio = 1 - ratio;
         var invRatio:Number = 1.0 - ratio;
         var r:int = 0x40 * ratio + 0xff * invRatio;
         var g:int = 0x80 * ratio + 0xff * invRatio;
         var b:int = 0x40;
         return (r<<16) + (g<<8) + (b);
    }

    public function draw():void{
        var col0:int, col1:int;
        switch( Status ){
        case 0: col0 = col1 = ColGreen;   break;
        case 1: col0 = col1 = getColYellowRatio(); break;
        case 2: col0 = ColRed0; col1 = ColRed1; break;
        case 3: col0 = col1 = ColBlue;    break;
        case 4: col0 = col1 = ColGray;    break;
        }
        BmpData.setPixel(X,   Y, col0);  
        setPixel(X+1, Y, col1);  
        setPixel(X,   Y+1, col1);  
        setPixel(X+1, Y+1, col1);  
    }
}

function setPixel( x:int, y:int, col:int):void{
    if( BmpData.getPixel(x, y) == BgColor ){    
        BmpData.setPixel(x,y, col);  
    }
}
        

import flash.events.*;
import flash.utils.*;
import flash.text.*;
import flash.ui.Keyboard;

class InputArea {
    public function InputArea( x:int, y:int, str:String, num:String, func:Function ){
        var tx:TextField = new TextField();
        tx.text = str;
        tx.x = x;
        tx.y = y;
        Main.addChild(tx); 

        var textArea:InputTextArea = new InputTextArea(func);
        textArea.x = 1 + x + str.length * 10;
        textArea.y = y;
        textArea.text = num;
        Main.addChild(textArea); 
    }
}

class InputTextArea extends TextField {
    public var Func:Function;
    public var myTimer:Timer = new Timer(2, 1);

    public function InputTextArea( func:Function ) {
        border = true;
        borderColor = 0xCCCCCC;
        width = 24;
        height = 16;
        type = TextFieldType.INPUT;
        restrict = "0-9";
        Func = func;
        var format:TextFormat = new TextFormat( "AXIS Std R", 12, 0, true );
        format.align = "right";
 
        defaultTextFormat = format;
        addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
        addEventListener(Event.CHANGE, function(e:Event):void{Func(text);});


        myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
        addEventListener(FocusEvent.FOCUS_IN, function(e:Event):void{ myTimer.start(); });
    }

    private function timerHandler(e:Event):void {
        setSelection(0, length);
    } 

    private function keyDownHandler(event:KeyboardEvent):void {
        if ( event.keyCode == Keyboard.ENTER ) {
            var inputText:String = text;
            Func(text);
            dispatchEvent( new InputEvent( InputEvent.INPUT_ENTER, inputText ) );
        }
    }
}



flash.events.Event;

class InputEvent extends Event {
    public static const INPUT_ENTER:String = "InputEvent.inputEnter";
    private var _text:String = "";
		
    public function InputEvent(type:String, text:String, bubbles:Boolean=false, cancelable:Boolean=false) { 
        super(type, bubbles, cancelable);
        _text = text;
    } 
		
    public override function clone():Event { 
        return new InputEvent(type, _text, bubbles, cancelable);
    } 
		
    public override function toString():String { 
        return formatToString("InputEvent", "text", "type", "bubbles", "cancelable", "eventPhase"); 
    }
		
    public function get text():String { return _text; }
}


import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.geom.Matrix;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;

class Button extends Sprite{
    private static const mono:ColorMatrixFilter = new ColorMatrixFilter([
        1 / 3, 1 / 3, 1 / 3, 0, 10,
        1 / 3, 1 / 3, 1 / 3, 0, 10,
        1 / 3, 1 / 3, 1 / 3, 0, 10,
            0,     0,     0, 1, 0
    ]);

    private var _textField:TextField = new TextField();
    private var _size:int;

    private var _hover:Boolean = false;
    public function get hover():Boolean{
        return _hover;
    }
    public function set hover(value:Boolean):void{
        if(_hover != value){
            _hover = value;
            filters = (_hover ? null : [mono]);
        }
    }

    public function Button(W:Number, H:Number, R:Number, label:String = "", size:int = 11){
        var matrix:Matrix = new Matrix();
        matrix.createGradientBox(W, H, Math.PI / 2);

        var bg:Sprite = new Sprite();

        bg.graphics.beginGradientFill("linear", [0x8c99a4, 0xc5d4e1, 0xBAD2E8], [1, 1, 1],
            [0, 120, 136], matrix);
        bg.graphics.drawRoundRect(0, 0, W, H, R, R);
        bg.graphics.endFill();

        bg.filters = [new GlowFilter(0xFFFFBE, .5, 10, 10, 2, 1, true)];
        addChild(bg);

        var line:Sprite = new Sprite();
        line.graphics.lineStyle(3, 0xBAD2E8);
        line.graphics.drawRoundRect(0, 0, W, H, R, R);
        addChild(line);

        filters = [mono];
        buttonMode = true;
        mouseChildren = false;

        if (label != ""){
            _size = size;
            _textField.selectable = false;
            _textField.autoSize = "left";
            _textField.htmlText = <font size={size} color="#4B4349">{label}</font>.toXMLString();
            _textField.x = (W - _textField.width) / 2;
            _textField.y = (H - _textField.height) / 2;
            addChild(_textField);
        }

        addEventListener("rollOver", buttonRollOver);
        addEventListener("rollOut", buttonRollOut);
        addEventListener("removed", function(event:Event):void{
            removeEventListener("rollOver", buttonRollOver);
            removeEventListener("rollOut", buttonRollOut);
            removeEventListener("removed", arguments.callee);
        });
    }
    public function setLabel( label:String ):void{
        _textField.htmlText = <font size={_size} color="#4B4349">{label}</font>.toXMLString();
    }

    protected function buttonRollOver(event:Event):void{
        hover = true;
    }

    protected function buttonRollOut(event:Event):void{
        hover = false;
    }
}


// エージェントを殺す
function killAgent(mx:int, my:int):void{
    var nearDist:int = 99999999, dist:int;
    var dx:int, dy:int;
    var delAgent :Agent = null;
    for each( var agent:Agent in AgentAry ){
        if( agent.Status == 4 ) continue;
        dx = agent.X - mx;
        dy = agent.Y - my;
        dist = dx*dx+dy*dy;
        if( dist < 4*3 && nearDist > dist ){
            nearDist = dist;
            delAgent = agent;
        }
    }

    if( delAgent != null ){
        delAgent.Status = 4;
    }
}

// 消毒剤クラス
class Disinfectant{
    public var Px:int;
    public var Py:int;
    public var Radius:int;
    public var Life:int;
    public var Count:int;

    public function Disinfectant( x:int, y:int, radius:int, life:Number ){ 
        Px = x;
        Py = y;
        Radius = radius;
        Life = life;
        DisinfectantAry.push(this);
    }
    public function update():void{ 
       Life--;
        if( Life < 0 ){
            for(var i:int = 0; i < DisinfectantAry.length; i++){
                if(DisinfectantAry[i] == this){
                    DisinfectantAry.splice(i,1);
                }
            }
        }


       Tex.delPower( Px, Py, Radius );    
    }

    public function draw():void{ 
        var col:int = Life;
        darwCircle( Px, Py, Radius, col + (col<<8)+(col<<16) );
    }
}

// 牧場クラス
class Farm{
    public var Px:int;
    public var Py:int;
    public var Width:int;
    public var Height:int;

    public function Farm( x:int, y:int, w:int, h:int, num:int, ratio:Number ){ 
        Px = x;
        Py = y;
        Width = w;
        Height = h;
        var agent:Agent;
        var ratioNow:Number = 0.001;
        var ratioAdd:Number = 1/num;
        var status:int = 0;
        for( var i:int=0; i<num; i++,ratioNow+=ratioAdd ){
            if( ratio < ratioNow )  status = 0;
            else                    status = 1;
            agent = new Agent( x+1,y+1,w-2,h-2, status );
        }
        FarmAry.push(this);
    }

    public function draw():void{ 
        darwWall( Px, Py, Width, Height, WallColor );
    }
}

// テクスチャ生成クラス
class ProcTex{ 
    public var BmpData:BitmapData;  
    public var BmpDataCopy:BitmapData;  
    public var TmpBmpData:BitmapData;  
    public var Bmp:Bitmap; 
    public var Width:int; 
    public var Height:int; 
    public var HeightBuf:Array;  
    public var HeightIdxDst:int;
    public var HeightIdxSrc0:int;
    public var BufWidth:int; 
    public var BufHeight:int; 
        
    public var PixelBufSize:int = 256;  
    public var PixelBuf:Vector.<int>;  

    public function ProcTex( w:int, h:int, useBmpData:BitmapData ){ 
        Width = w; 
        Height = h; 
        BmpDataCopy = useBmpData
        BmpData = new BitmapData(Width, Height, false, 0xffffff);  
        Bmp = new Bitmap(BmpData);  
       // Bmp.scaleX = 2.0; 
       // Bmp.scaleY = 2.0; 
        Main.addChild(Bmp);       

        // 波高バッファの生成
         HeightBuf = new Array;  
        BufWidth = Width+2;
        BufHeight = Height+2;
        clear();
    } 

    public function clear():void{ 
        HeightBuf[0] = new Vector.<Number>;
        HeightBuf[1] = new Vector.<Number>;
        HeightBuf[2] = new Vector.<Number>;
        for( var x:int=-1; x<Width+1; x++ ){  
            for( var y:int=-1; y<Height+1; y++ ){
                var idx:int = (x+1) + (y+1)*BufWidth;
                HeightBuf[0].push( 0 );
                HeightBuf[1].push( 0 );
                HeightBuf[2].push( 0 );
            }
        }
        HeightIdxSrc0=0;
        HeightIdxDst=1;
    }

    public function draw():void{ 
        HeightIdxSrc0++;
        HeightIdxDst++;
        if( HeightIdxSrc0 > 1 ) HeightIdxSrc0 = 0;
        if( HeightIdxDst  > 1 ) HeightIdxDst  = 0;
        calcWave();     
        createBmp( HeightIdxDst );     
    }

    // 水面に力を加える
    public function addPower( px:int, py:int, pow:Number ):void{ 
        var r:int = 6;
        var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
        for( var lx:int=-r; lx<=r; lx++ ){  
            for( var ly:int=-r; ly<=r; ly++ ){
                const d:Number = Math.sqrt(lx*lx+ly*ly); 
                if (d < r) { 
                    var p:Number = Math.cos(Math.PI/2 * d/r); 
                    var x:int = px + lx;  
                    var y:int = py + ly;  
                    if( x < 0 || x >= Width || y < 0 || y >= Height ) break;
                    var idx:int = (x+1) + (y+1)*BufWidth;
                    buf[idx] += pow * p;
                    if( buf[idx] < 0 ) buf[idx] = 0;
                } 
            }
        }
    }

    // 水面に力を加える
    public function delPower( px:int, py:int, r:int ):void{ 
        var rr:int = r*r;
        var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
        for( var lx:int=-r; lx<=r; lx++ ){  
            for( var ly:int=-r; ly<=r; ly++ ){
                const d:Number = lx*lx+ly*ly; 
                if (d < rr) { 
                    var x:int = px + lx;  
                    var y:int = py + ly;  
                    if( x < 0 || x >= Width || y < 0 || y >= Height ) break;
                    var idx:int = (x+1) + (y+1)*BufWidth;
                    buf[idx] = 0;
                } 
            }
        }
    }

    public function getPower( x:int, y:int ):Number{ 
        if( x < 0 || x >= Width || y < 0 || y >= Height ) return 0;
        var idx:int = (x+1) + (y+1)*BufWidth;
        var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
        return buf[idx];
    }

    // 水面画像の生成
    public function createBmp( idx:int ):void{ 
        var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
        var col:Number, colU:Number, colL:Number, vecX:Number, vecY:Number; 
        var idx:int, ix:int, iy:int;
        var r:int, g:int, b:int, pixCol:int, add:int;
        BmpData.lock();
        for( var x:int=0; x<Width; x++ ){  
            for( var y:int=0; y<Height; y++ ){
                idx = (x+1) + (y+1)*BufWidth;
                col = buf[idx];
                pixCol = BmpDataCopy.getPixel(x, y);
                r = (pixCol&0x0000ff);
                g = (pixCol&0x00ff00)>>8;
                b = (pixCol&0xff0000)>>16;
                add = col * 64;
                if( add > 128 ) add = 128;
                b += add;
                if( b > 255 ) b = 255;
                if( b < 0 ) b = 0;
                pixCol = r + (g<<8) + (b<<16);
                BmpData.setPixel(x, y, pixCol);//col);  
            }
        }    
        BmpData.unlock();
    }

    // 波計算
    public function calcWave():void{ 
        var srcBuf0:Vector.<Number> = HeightBuf[HeightIdxSrc0];
        var dstBuf:Vector.<Number> = HeightBuf[HeightIdxDst];
        var idx:int, idxU:int, idxD:int, idxL:int, idxR:int;
        for( var x:int=1; x<Width-6-1; x++ ){  
            for( var y:int=1; y<Height-6-1; y++ ){
                idx  = (x+2) + (y+2)*BufWidth;
                idxU = (x+2) + (y  )*BufWidth;
                idxD = (x+2) + (y+4)*BufWidth;
                idxL = (x  ) + (y+2)*BufWidth;
                idxR = (x+4) + (y+2)*BufWidth;
                dstBuf[idx] = 0.20 * (srcBuf0[idx] + srcBuf0[idxU] + srcBuf0[idxD] + srcBuf0[idxL] + srcBuf0[idxR]);
                dstBuf[idx] *= 0.999;
            }
        }    
    } 
}



var KEY_UP:int    = 0x01;
var KEY_DOWN:int  = 0x02;
var KEY_LEFT:int  = 0x04;
var KEY_RIGHT:int = 0x08;
var KEY_SHIFT:int = 0x08;
var KeyData:int;
function keyCheckDown(event:KeyboardEvent):void { 
    switch (event.keyCode){ 
        case Keyboard.UP:	    KeyData |= KEY_UP; break;
        case Keyboard.DOWN:	    KeyData |= KEY_DOWN; break;
        case Keyboard.LEFT:    KeyData |= KEY_LEFT; break;
        case Keyboard.SHIFT:   KeyData |= KEY_SHIFT; break;
    }
} 
function keyCheckUp(event:KeyboardEvent):void { 
    switch (event.keyCode){ 
        case Keyboard.UP:      KeyData &= ~KEY_UP; break;
        case Keyboard.DOWN:    KeyData &= ~KEY_DOWN; break;
        case Keyboard.LEFT:    KeyData &= ~KEY_LEFT; break;
        case Keyboard.RIGHT:   KeyData &= ~KEY_RIGHT; break;
        case Keyboard.SHIFT:   KeyData &= ~KEY_SHIFT; break;
    }
}