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

RogueLikeSimulator

ローグライクのダンジョンを自動生成して、エネミーを動かしてみる。
      無理やりコードを一つにまとめたらとんでもなくひどいものになったけど
      せっかくなので公開しました。
      
      Enter:ダンジョン再構築

スマホ向けローグライクを作り始めました https://twitter.com/rogue_inu
Get Adobe Flash player
by inu 09 May 2013
/**
 * Copyright inu ( http://wonderfl.net/user/inu )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tEAA
 */

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    
    [SWF(width="465",height="465",frameRate="60")]
    
    /**
     * ...
     * @author inu
      ローグライクのダンジョンを自動生成して、エネミーを動かしてみる。
      無理やりコードを一つにまとめたらとんでもなくひどいものになったけど
      せっかくなので公開しました。
      
      Enter:ダンジョン再構築
      
      スマホ向けローグライクを作り始めました https://twitter.com/rogue_inu
      
     */
    public class Main extends Sprite 
    {
        
        private var floor:Floor;
        private var ef:EnemyFactory;
        private var minimap:MiniMap;
        private var debug:Debug;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            newFloor();
            
            addEventListener(Event.ENTER_FRAME, ent);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownEvent);
        }
        
        private function keyDownEvent(e:KeyboardEvent):void 
        {
            if (e.keyCode == Keyboard.ENTER) {
                newFloor();
            }
        }
        
        private function newFloor():void {
            removeChildren();
            floor = null;
            ef = null;
            minimap = null;
            debug = null;
            if (int(Math.random() * 2)) floor = new FloorNormal();
            else floor = new FloorUnion();
            ef = new EnemyFactory(floor);
            for(var i:int = 0; i < 1; i++){
                ef.create();
            }
            minimap = new MiniMap(floor, ef);
            minimap.newMiniMap();
            debug = new Debug(floor, ef);
            addChild(minimap);
            addChild(debug);
        }
        
        private function ent(e:Event):void {
            ef.update();
            minimap.draw();
            debug.update();
            if (ef.ready()) ef.turnUpdate();
        }
        
    }
    
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.utils.getTimer;

class Floor //フロア
{
    protected var vec2Grid:Vector.<Vector.<Grid>>;
    protected var vecRoom:Vector.<Room>;
    
    public var turn:int = 0;
    public function Floor():void {
        turn = 0;
        create();
    }
    
    public function getGrid(gridX:int, gridY:int ):Grid {
        if (gridX < 0 || gridY < 0 || gridX >= 59 || gridY >= 35) return Grid.dummy;
        return vec2Grid[gridY][gridX];
    }
    
    public function getGridByPoint(point:Point):Grid {
        if (point.x < 0 || point.y < 0 || point.x >= 59 || point.y >= 35) return Grid.dummy;
        return vec2Grid[point.y][point.x];
    }
    
    public function getRoom(roomN:int):Room {
        var i:int;
        for(i = 0; i < vecRoom.length; i++){
            if (vecRoom[i].roomN == roomN) return vecRoom[i];
        }
        return null;
    }
    
    public function getRandomRoom():Room {
        var i:int;
        return vecRoom[Rand.getInt(vecRoom.length)];
    }
    
    public function getRandomRoomGrid():Grid {
        var room:Room = getRandomRoom();
        var point:Point = room.getRandomPoint();
        return vec2Grid[room.gridY + point.y][room.gridX + point.x];
    }
    
    public function setChar(char:Character):void {
        vec2Grid[char.gridY][char.gridX].char = char;
    }
    
    public function removeChar(char:Character):void {
        vec2Grid[char.gridY][char.gridX].char = null;
    }
    
    public function setExitPointToRoom():void {
        var i:int, j:int, k:int;
        var room:Room;
        var grid:Grid;
        var rx:int, ry:int;
        var len:int = vecRoom.length;
        for(k = 0; k < len; k++){
            room = vecRoom[k];
            rx = room.gridX;
            ry = room.gridY;
            room.vecExitPoint = null;
            room.vecExitPoint = new Vector.<Point>();
            for (i = -1; i < room.gridH + 1; i++) for (j = - 1; j < room.gridW + 1; j++) {
                grid = vec2Grid[ry + i][rx + j];
                if (grid.type == 1) {
                    grid.roomExitN = room.roomN;
                    room.vecExitPoint.push(new Point(rx + j, ry + i));
                }
            }
            if (room.vecExitPoint.length == 0) trace("t");//どこにもつながってない部屋
        }
        
    }
    
    //移動チェック -1:壁 -2:キャラ
    public function moveCheck(char:Character, d:int):int {
        var point:Point = Move.point(d);
        var grid2:Grid = getGrid(char.gridX + point.x, char.gridY + point.y);
        
        if (d % 2 == 1) {
            var grid3:Grid;
            var grid4:Grid;
            point = Move.point(d + 1);
            grid3 = getGrid(char.gridX + point.x, char.gridY + point.y);
            point = Move.point(d - 1);
            grid4 = getGrid(char.gridX + point.x, char.gridY + point.y);
            if (grid2.type == 0 || grid3.type == 0 || grid4.type == 0) {
                return -1;
            }
            if (grid2.char != null) {
                return -2;
            }
            
        }else {
            if (grid2.type == 0) return -1;
            if (grid2.char != null) return -2;
        }
        
        return 0;
    }
    
    //フロア作成中しか使わない**********************************************************************************
    
    protected var divW:int, divH:int;
    protected var rectW:int, rectH:int;
    protected var vec2Rect:Vector.<Vector.<Rect>>;
    protected var vec2RoadH:Vector.<Vector.<Road>>;
    protected var vec2RoadV:Vector.<Vector.<Road>>;
    
    protected function create():void {
        trace("virtual");
    }
    
    //フロア作成中しか使わない
    protected function initGrid():void {
        var i:int, j:int;
        //初期化
        vec2Grid = new Vector.<Vector.<Grid>>();
        for (i = 0; i < 35; i++) {
            vec2Grid.push(new Vector.<Grid>());
            for (j = 0; j < 59; j++) {
                vec2Grid[i][j] = new Grid(j, i);
            }
        }
    }
    
    //フロア作成中しか使わない
    protected function initRect():void {
        //区画設定
        var i:int, j:int;
        
        //マップを区画分け
        divW = Rand.minmax(3, 6);
        divH = Rand.minmax(3, 4);
        rectW = (59 - divW + 1) / divW;
        rectH = (35 - divH + 1) / divH;
        
        //初期化
        vec2Rect = new Vector.<Vector.<Rect>>();
        for (i = 0; i < divH; i++) {
            vec2Rect.push(new Vector.<Rect>());
            for (j = 0; j < divW; j++) {
                vec2Rect[i][j] = new Rect(j * (rectW + 1), i * (rectH + 1), rectW, rectH);
                vec2Rect[i][j].room = new Room(0, 0, 0, 0);
                vec2Rect[i][j].room.roomN = i * divW + j;
            }    
        }
    }
    
    //connectRect();
    
    //フロア作成中しか使わない
    protected function initRoad():void {
        //通路設定
        var i:int, j:int;
        vec2RoadH = new Vector.<Vector.<Road>>();
        vec2RoadV = new Vector.<Vector.<Road>>();
        
        for (i = 0; i < divH; i++) {
            vec2RoadH.push(new Vector.<Road>());
            for (j = 0; j < divW - 1; j++) {
                if (vec2Rect[i][j] == vec2Rect[i][j + 1]) { vec2RoadH[i][j] = null; continue;}
                vec2RoadH[i][j] = new Road(j * (rectW + 1) + rectW, i * (rectH + 1), 1, rectH );
                vec2RoadH[i][j].room1 = vec2Rect[i][j].room;//左の部屋
                vec2RoadH[i][j].room2 = vec2Rect[i][j + 1].room;//右の部屋
                
            }
        }
        
        for (i = 0; i < divH - 1; i++) {
            vec2RoadV.push(new Vector.<Road>());
            for (j = 0; j < divW; j++) {
                if (vec2Rect[i][j] == vec2Rect[i + 1][j]) {vec2RoadV[i][j] = null; continue;}
                vec2RoadV[i][j] = new Road(j * (rectW + 1), i * (rectH + 1) + rectH, rectW, 1);
                vec2RoadV[i][j].room1 = vec2Rect[i][j].room;//上の部屋
                vec2RoadV[i][j].room2 = vec2Rect[i + 1][j].room;//下の部屋
            }
        }
        
    }
    
    //フロア作成中しか使わない
    protected function createMaze():void {
        //棒倒し的に
        var i:int, j:int;
        
        for (i = 0; i < divH - 1; i++) for (j = 0; j < divW - 1; j++) { 
            //上下左右に棒倒し 通路を消して上下、左右の区画を拡張
            
            switch(Rand.getInt(6)*2) {
                case 0:
                    if (vec2RoadH[i][j] == null) continue;
                    vec2RoadH[i][j] =  null;
                    if (!vec2Rect[i][j].room.isConnectedV) vec2Rect[i][j].gridW++;
                    if (!vec2Rect[i][j + 1].room.isConnectedV) {
                        vec2Rect[i][j + 1].gridW++;
                        vec2Rect[i][j + 1].gridX--;
                    }
                    break;
                case 2:
                    if (vec2RoadV[i][j + 1] == null) continue;
                    vec2RoadV[i][j + 1] =  null;
                    if (!vec2Rect[i][j + 1].room.isConnectedH) vec2Rect[i][j + 1].gridH++;
                    if (!vec2Rect[i + 1][j + 1].room.isConnectedH) {
                        vec2Rect[i + 1][j + 1].gridH++;
                        vec2Rect[i + 1][j + 1].gridY--;
                    }
                    break;
                case 4:
                    if (vec2RoadH[i + 1][j] == null) continue;
                    vec2RoadH[i + 1][j] =  null;
                    if (!vec2Rect[i + 1][j].room.isConnectedV) vec2Rect[i + 1][j].gridW++;
                    if (!vec2Rect[i + 1][j + 1].room.isConnectedV) {
                        vec2Rect[i + 1][j + 1].gridW++;
                        vec2Rect[i + 1][j + 1].gridX--;
                    }
                    break;
                case 6:
                    if (vec2RoadV[i][j] == null) continue;
                    vec2RoadV[i][j] =  null;
                    if (!vec2Rect[i][j].room.isConnectedH) vec2Rect[i][j].gridH++;
                    if (!vec2Rect[i + 1][j].room.isConnectedH) {
                        vec2Rect[i + 1][j].gridH++;
                        vec2Rect[i + 1][j].gridY--;
                    }
                    break;
            }
            
        }
        
        
        var loopCnt:int;//無限ループ防ぎ
        var loopLength:int = Rand.minmax(divH*divW/5,divH*divW/4)
        for (i = 0; i < loopLength; i++) {//通路部屋の作成
            loopCnt++; if (loopCnt > 100) break;
            var rx:int = Rand.getInt(divW);
            var ry:int = Rand.getInt(divH);
            if (vec2Rect[ry][rx].room.roomN == -1 || vec2Rect[ry][rx].room.isConnected()) {
                i--; continue; //被ったらコンティニュー
            }else {//部屋の大きさを1グリッドにする
                vec2Rect[ry][rx].room.roomN = -1;
                vec2Rect[ry][rx].room.gridW = 1;
                vec2Rect[ry][rx].room.gridH = 1;
            }
        }
        
        
    }
    
    //フロア作成中しか使わない
    protected function createRoom():void {
        //区画に部屋を作成
        var i:int, j:int;
        var roomX:int, roomY:int, roomH:int, roomW:int;
        
        vecRoom = new Vector.<Room>();
        for (i = 0; i < divH; i++) for (j = 0; j < divW; j++) {
            var rect:Rect = vec2Rect[i][j];
            var room:Room = rect.room;
            if (room.gridX != 0) continue;
            
            if (room.roomN != -1) {//通常の部屋だったら
                
                if (room.isConnectedH) roomW = Rand.minmax(rectW + rect.gridW % rectW + 1, rect.gridW - 2);
                else roomW = Rand.minmax(rect.gridW / 2, rect.gridW - 2);
                if (room.isConnectedV) roomH = Rand.minmax(rectH + rect.gridH % rectH + 1, rect.gridH - 2);
                else roomH = Rand.minmax(rect.gridH / 2, rect.gridH - 2);
                
                room.gridW = roomW;
                room.gridH = roomH;
            }
            
            roomX = rect.gridX + Rand.minmax(1, rect.gridW - room.gridW - 1);
            roomY = rect.gridY + Rand.minmax(1, rect.gridH - room.gridH - 1);
            //min 1,1
            
            room.gridX = roomX;
            room.gridY = roomY;
            
            vecRoom.push(room);
        }
    }
    
    //フロア作成中しか使わない
    protected function createRoad():void {
        var i:int, j:int;
        var road:Road;
        
        for (i = 0; i < divH; i++) for (j = 0; j < divW - 1; j++) {
            road = vec2RoadH[i][j];
            if (road == null) continue;
            
            var room1nodeY:int = Rand.minmax(Math.max(i * (rectH + 1), road.room1.gridY + 1) , Math.min( (i + 1) * (rectH + 1) - 2, road.room1.getBottomGridY() - 1));
            var room2nodeY:int = Rand.minmax(Math.max(i * (rectH + 1), road.room2.gridY + 1) , Math.min( (i + 1) * (rectH + 1) - 2, road.room2.getBottomGridY() - 1));
            if (road.room1.roomN == -1) room1nodeY = road.room1.gridY;
            if (road.room2.roomN == -1) room2nodeY = road.room2.gridY;
            
            road.gridH = Math.abs(room1nodeY - room2nodeY) + 1;
            road.gridY = Math.min(room1nodeY, room2nodeY);
            road.gridX = Rand.minmax(road.room1.getRightGridX() + 2, road.room2.gridX - 2);
            
            if (road.gridY == room1nodeY) road.nodeType = 0;
            else road.nodeType = 1;
            
        }
        
        
        for (i = 0; i < divH - 1; i++) for (j = 0; j < divW; j++) {
            road = vec2RoadV[i][j];
            if (road == null) continue;
            
            var room1nodeX:int = Rand.minmax(Math.max(j * (rectW + 1), road.room1.gridX + 1) , Math.min( (j + 1) * (rectW + 1) - 2, road.room1.getRightGridX() - 1));
            var room2nodeX:int = Rand.minmax(Math.max(j * (rectW + 1), road.room2.gridX + 1) , Math.min( (j + 1) * (rectW + 1) - 2, road.room2.getRightGridX() - 1));
            if (road.room1.roomN == -1) room1nodeX = road.room1.gridX;
            if (road.room2.roomN == -1) room2nodeX = road.room2.gridX;
            
            road.gridW = Math.abs(room1nodeX - room2nodeX) + 1;
            road.gridX = Math.min(room1nodeX, room2nodeX);
            road.gridY = Rand.minmax(road.room1.getBottomGridY() + 2, road.room2.gridY - 2);
            
            if (road.gridX == room1nodeX) road.nodeType = 0;
            else road.nodeType = 1;
            
        }
        
    }
    
    //フロア作成中しか使わない
    protected function insertToGrid():void {
        var i:int, j:int, k:int, l:int;
        var room:Room;
        var road:Road;
        
        for (k = 0; k < vecRoom.length; k++) {//部屋を反映
            room = vecRoom[k];
            if (room.roomN == -1) {
                //通路部屋だったら通路と判定し、vecRoomから除外
                vec2Grid[room.gridY][room.gridX].type = 1;
                vecRoom.splice(k--, 1);
                continue;
            }
            for(i = 0; i < room.gridH; i++)for(j = 0; j < room.gridW; j++){
                vec2Grid[room.gridY + i][room.gridX + j].type = 2;
                vec2Grid[room.gridY + i][room.gridX + j].roomN = room.roomN;
            }
        }
        
        for(k = 0; k < divH; k++)for(l = 0; l < divW - 1; l++){//通路を反映
            road = vec2RoadH[k][l];
            if (road == null) continue;
            
            for(i = 0; i < road.gridH; i++)for(j = 0; j < road.gridW; j++){
                vec2Grid[road.gridY + i][road.gridX + j].type = 1;
            }
            
            for (i = 1; 1;i++ ) {
                if (road.nodeType == 0) {
                    if (vec2Grid[road.gridY][road.gridX - i].type == 0) {
                        vec2Grid[road.gridY][road.gridX - i].type = 1;
                    }else break;
                }else {
                    if (vec2Grid[road.gridY][road.gridX + i].type == 0) {
                        vec2Grid[road.gridY][road.gridX + i].type = 1;
                    }else break;
                }
            }
            for (i = 1; 1;i++ ) {
                if (road.nodeType == 0) {
                    if (vec2Grid[road.getBottomGridY()][road.gridX + i].type == 0) {
                        vec2Grid[road.getBottomGridY()][road.gridX + i].type = 1;
                    }else break;
                    
                }else {
                    if (vec2Grid[road.getBottomGridY()][road.gridX - i].type == 0) {
                        vec2Grid[road.getBottomGridY()][road.gridX - i].type = 1;
                    }else break;
                    
                }
            }
        }
        
        for(k = 0; k < divH - 1; k++)for(l = 0; l < divW; l++){//通路を反映
            road = vec2RoadV[k][l];
            if (road == null) continue;
            
            for(i = 0; i < road.gridH; i++)for(j = 0; j < road.gridW; j++){
                vec2Grid[road.gridY + i][road.gridX + j].type = 1;
            }
            
            for (i = 1; 1;i++ ) {
                if (road.nodeType == 0) {
                    if (vec2Grid[road.gridY - i][road.gridX].type == 0) {
                        vec2Grid[road.gridY - i][road.gridX].type = 1;
                    }else break;
                }else {
                    if (vec2Grid[road.gridY + i][road.gridX].type == 0) {
                        vec2Grid[road.gridY + i][road.gridX].type = 1;
                    }else break;
                }
            }
            for (i = 1; 1;i++ ) {
                if (road.nodeType == 0) {
                    if (vec2Grid[road.gridY + i][road.getRightGridX()].type == 0) {
                        vec2Grid[road.gridY + i][road.getRightGridX()].type = 1;
                    }else break;
                    
                }else {
                    if (vec2Grid[road.gridY - i][road.getRightGridX()].type == 0) {
                        vec2Grid[road.gridY - i][road.getRightGridX()].type = 1;
                    }else break;
                    
                }
            }
        }
        
    }
}

class FloorNormal extends Floor
{
    
    override protected function create():void {
        initGrid();//グリッド初期化
        initRect();//区画の初期化
        initRoad();//通路の初期化
        createMaze();//区画を迷路化
        createRoom();//部屋を作成
        createRoad();//通路を作成
        insertToGrid();//作った部屋などをvec2Gridに反映
        setExitPointToRoom();//部屋に出口を設定
    }
    
}

class FloorUnion extends Floor
{
    
    override protected function create():void {
        initGrid();//グリッド初期化
        initRect();//区画の初期化
        connectRect();//区画を繋げる********
        initRoad();//通路の初期化
        createMaze();//区画を迷路化
        createRoom();//部屋を作成
        createRoad();//通路を作成
        insertToGrid();//作った部屋などをvec2Gridに反映
        setExitPointToRoom();//部屋に出口を設定
    }
    
    private function connectRect():void{
        var i:int, j:int;
        for(i = 0; i < divH - 1; i++)for(j = 0; j < divW - 1; j++){//区画を繋げる
            switch(Rand.getInt(5)) {
                case 0://左上と右上の区画をつなげる
                    if (vec2Rect[i][j].room.isConnected()|| vec2Rect[i][j + 1].room.isConnected()) continue;
                    //if (vec2Rect[i][j] == vec2Rect[i][j + 1]) continue;
                    vec2Rect[i][j + 1] = null;
                    vec2Rect[i][j + 1] = vec2Rect[i][j];
                    vec2Rect[i][j].gridW += rectW + 1;
                    vec2Rect[i][j].room.isConnectedH = true;
                    break;
                case 1://右上と右下
                    if (vec2Rect[i][j + 1].room.isConnected() || vec2Rect[i + 1][j + 1].room.isConnected()) continue;
                    //if (vec2Rect[i + 1][j + 1] == vec2Rect[i][j + 1]) continue;
                    vec2Rect[i + 1][j + 1] = null;
                    vec2Rect[i + 1][j + 1] = vec2Rect[i][j + 1];
                    vec2Rect[i][j + 1].gridH += rectH + 1;
                    vec2Rect[i][j + 1].room.isConnectedV = true;
                    break;
                case 2://右下と左下
                    if (vec2Rect[i + 1][j].room.isConnected() || vec2Rect[i + 1][j + 1].room.isConnected()) continue;
                    //if (vec2Rect[i + 1][j + 1] == vec2Rect[i + 1][j]) continue;
                    vec2Rect[i + 1][j + 1] = null;
                    vec2Rect[i + 1][j + 1] = vec2Rect[i + 1][j];
                    vec2Rect[i + 1][j].gridW += rectW + 1;
                    vec2Rect[i + 1][j].room.isConnectedH = true;
                    break;
                case 3://左下と左上
                    if (vec2Rect[i][j].room.isConnected() || vec2Rect[i + 1][j].room.isConnected()) continue;
                    if (vec2Rect[i + 1][j] == vec2Rect[i][j]) continue;
                    vec2Rect[i + 1][j] = null;
                    vec2Rect[i + 1][j] = vec2Rect[i][j];
                    vec2Rect[i][j].gridH += rectH + 1;
                    vec2Rect[i][j].room.isConnectedV = true;
                    break;
                case 4://4つくっつける
                    if (vec2Rect[i][j].room.isConnected() || vec2Rect[i][j + 1].room.isConnected() || vec2Rect[i + 1][j].room.isConnected()) continue;
                    if (vec2Rect[i][j] == vec2Rect[i][j + 1] || vec2Rect[i][j] == vec2Rect[i + 1][j] || vec2Rect[i][j] == vec2Rect[i + 1][j + 1]) continue;
                    vec2Rect[i + 1][j] = null;
                    vec2Rect[i + 1][j] = vec2Rect[i][j];
                    vec2Rect[i][j + 1] = null;
                    vec2Rect[i][j + 1] = vec2Rect[i][j];
                    vec2Rect[i + 1][j + 1] = null;
                    vec2Rect[i + 1][j + 1] = vec2Rect[i][j];
                    vec2Rect[i][j].gridW += rectW + 1;
                    vec2Rect[i][j].gridH += rectH + 1;
                    vec2Rect[i][j].room.isConnectedH = true;
                    vec2Rect[i][j].room.isConnectedV = true;
                    break;
            }
        }
        
    }
    
}

class Grid
{
    public static const dummy:Grid = new (Grid)(0, 0);
    
    public var gridX:int;
    public var gridY:int;
    public var type:int;
    
    public var roomN:int = -1;
    public var roomExitN:int = -1;
    
    public var char:Character;
    
    public function Grid(gridX:int, gridY:int) 
    {
        this.gridX = gridX;
        this.gridY = gridY;
    }
    
    public function getGridPoint():Point{
        return new Point(gridX, gridY);
    }
}

class Rect //区画
{
    public var gridX:int;
    public var gridY:int;
    public var gridW:int;
    public var gridH:int;
    
    public var room:Room;
    
    public function Rect(gridX:int, gridY:int, gridW:int, gridH:int) 
    {
        this.gridX = gridX;
        this.gridY = gridY;
        this.gridW = gridW;
        this.gridH = gridH;
    }
    
}

class Road //通路
{
    public var gridX:int;
    public var gridY:int;
    public var gridW:int;
    public var gridH:int;
    
    public var room1:Room;
    public var room2:Room;
    public var nodeType:int;
    
    public function Road(gridX:int, gridY:int, gridW:int, gridH:int) 
    {
        this.gridX = gridX;
        this.gridY = gridY;
        this.gridW = gridW;
        this.gridH = gridH;
    }
    
    public function getBottomGridY():int {
        return gridY + gridH - 1;
    }
    
    public function getRightGridX():int {
        return gridX + gridW - 1;
    }
    
}

class Room //部屋
{
    
    public var gridX:int;
    public var gridY:int;
    public var gridW:int;
    public var gridH:int;
    
    public var isConnectedH:Boolean;
    public var isConnectedV:Boolean;
    
    public var vecExitPoint:Vector.<Point>;
    
    public var roomN:int = 0;
    
    public function Room(gridX:int, gridY:int, gridW:int, gridH:int) 
    {
        this.gridX = gridX;
        this.gridY = gridY;
        this.gridW = gridW;
        this.gridH = gridH;
    }
    
    public function isConnected():Boolean {
        if (isConnectedH || isConnectedV) return true;
        return false;
    }
    
    public function getBottomGridY():int {
        return gridY + gridH - 1;
    }
    
    public function getRightGridX():int {
        return gridX + gridW - 1;
    }
    
    public function getRandomPoint():Point {
        return new Point(Rand.getInt(gridW), Rand.getInt(gridH));
    }
    
    public function getRandomExitPoint(moveEnemy:Enemy):Point {//ランダムな出口を返す。距離1は除外
        if (vecExitPoint.length == 1) return vecExitPoint[0];
        var exitPoint:Point;
        while(true){
            exitPoint = vecExitPoint[Rand.getInt(vecExitPoint.length)];
            if (Point.distance(exitPoint, moveEnemy.getGridPoint()) != 1) return exitPoint;
        }
        return null;
    }
    
}

class Character extends Sprite
{
    public var gridX:int;
    public var gridY:int;
    public var pastGridX:int;
    public var pastGridY:int;
    
    //ステータス
    public var speed:int;
    public var direction:int;
    
    //アクション
    protected var action:Action;
    
    public var moveSpeed:int = 6;//移動スピード
    
    public var vecAction:Vector.<Action>;
    
    public var floor:Floor;
    
    public function Character(floor:Floor) 
    {
        this.floor = floor;
        vecAction = new Vector.<Action>();
    }
    
    public function update():void {
        //アクション
        if (vecAction.length != 0) {
            action = vecAction[0];
            if (action.startFunc != null) { action.startFunc(); action.startFunc = null; }
            action.frame--;
            x += action.moveX;
            y += action.moveY;
            if (action.frame == 0) {
                if (action.callback != null) action.callback();
                vecAction.shift();
            }
        }
    }

    public function draw():void {
        trace("virtual");
    }
    
    public function getPoint():Point{
        return new Point(x, y);
    }
    
    public function getGridPoint():Point{
        return new Point(gridX, gridY);
    }
    
    public function getPastGridPoint():Point {
        return new Point(pastGridX, pastGridY);
    }
    
    //現在の部屋番号を取得
    public function getRoomN():int {
        return floor.getGrid(gridX, gridY).roomN;
    }
    
    //現在の部屋を取得
    public function getRoom():Room {
        return floor.getRoom(floor.getGrid(gridX, gridY).roomN);
    }
    
    //現在のグリッドを取得
    public function getGrid():Grid {
        return floor.getGrid(gridX, gridY);
    }
    
    public function getPastGrid():Grid {
        return floor.getGrid(pastGridX, pastGridY);
    }
    
    public function init():void {
        gridX = 0;
        gridY = 0;
        pastGridX = 0;
        pastGridY = 0;
        warp();
    }
    
    public function move(d:int):Boolean {
        trace("virtual");
        return false;
    }
    
    //グリッドの移動
    public function moveGrid(gridX:int, gridY:int):void {
        floor.removeChar(this);//消す
        pastGridX = this.gridX;
        pastGridY = this.gridY;
        this.gridX = gridX;
        this.gridY = gridY;
        floor.setChar(this);//反映
    }
    
    //向き変更
    public function changeDirection(d:int):Boolean {
        if (d < 0 ) d += 8;
        if (d > 7) d -= 8;
        direction = d;
        return true;
    }
    
    //準備チェック
    public function ready():Boolean {
        if (vecAction.length == 0) return true;
        return false;
    }
    
    public function warp():void {
        var grid:Grid;
        for (var i:int = 0; i < 100; i++ ) {
            grid = floor.getRandomRoomGrid();
            if (grid.char == null) break;
        }
        if (i == 100) grid = floor.getGrid(gridX, gridY);
        
        moveGrid(grid.gridX, grid.gridY);
        x = grid.gridX * 48;
        y = grid.gridY * 48;
    }
    
    public function addAction(action:Action):void {
        vecAction.push(action);
    }
    
}

class Enemy extends Character 
{    
    public var actionPoint:int;
    
    public var targetPointTurn:int;
    public var targetPoint:Point;
    public var vecCandidate:Vector.<int>;
    
    public var moveEnd:Boolean = true;
    
    public function Enemy(floor:Floor)
    {
        super(floor);
        speed = 2//(int(Math.random() * 3) + 1) * 2;
        vecCandidate = new Vector.<int>();
    }
    
    public function turnUpdate():void {
        actionPoint += speed;
        while(actionPoint >= 2){
            actionPoint -= 2;
            moveEnd = false;
            updateTargetPoint();
            if (moveEnd) continue;
            setCandidate();
            tryCandidte();
        }
    }
    
    //ターゲットポイントを更新
    public function updateTargetPoint():void {
        var i:int;
        var roomN:int = getRoomN();
        var roomExitN:int = getGrid().roomExitN;
        var room:Room;
        var vecNear:Vector.<Point>;
        var nowGridPoint:Point = getGridPoint();
        
        targetPointTurn--;
        if (targetPoint != null) {
            if (targetPointTurn <= 0 || targetPoint.equals(nowGridPoint)) {
                targetPoint = null;
            }
            else if(getRoomN() != -1)return;
        }
        
        if (roomN == -1) {//通路にいたら
            vecNear = new Vector.<Point>();
            var point:Point;
            if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction))).type != 0) {
                vecNear.push(point);
            }
            if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction + 2))).type != 0) {
                vecNear.push(point);
            }
            if (floor.getGridByPoint(point = nowGridPoint.add(Move.point(direction - 2))).type != 0) { 
                vecNear.push(point);
            }
            
            if (vecNear.length != 0) targetPoint = vecNear[Rand.getInt(vecNear.length)];
            
            if(targetPoint == null || floor.getGridByPoint(targetPoint).char != null){
                changeDirection(direction + 4);
                targetPoint = null;
                
                moveEnd = true;
            }
            
        }else {//部屋にいたら
            room = getRoom();
            
            targetPoint = room.getRandomExitPoint(this);
            targetPointTurn = Point.distance(targetPoint, nowGridPoint) + 10;
        }
    }
    
    
    //移動候補を設定
    public function setCandidate():void {
        var d:int = Move.direction(targetPoint.subtract(getGridPoint()));
        
        if (Rand.getInt(2)) vecCandidate.push(Move.fixDirection(d + 1), Move.fixDirection(d - 1));
        else vecCandidate.push(Move.fixDirection(d - 1), Move.fixDirection(d + 1));
        
        if (Rand.getInt(2)) vecCandidate.push(Move.fixDirection(d + 2), Move.fixDirection(d - 2));
        else vecCandidate.push(Move.fixDirection(d - 2), Move.fixDirection(d + 2));
        
        //ターゲットポイントに近い順にソート
        if (d % 2 == 1) vecCandidate.sort(distanceSort);
        vecCandidate.unshift(d);
        
        //ソート関数
        function distanceSort(a:int, b:int):Number{
            return Point.distance(getGridPoint().add(Move.point(a)), targetPoint) - Point.distance(getGridPoint().add(Move.point(b)), targetPoint);
        }
    }
    
    public function tryCandidte():void {
        if (vecCandidate.length == 0) return;
        if (!move(vecCandidate[0])) tryCandidte();
    }
    
    override public function move(d:int):Boolean {
        var point:Point = Move.point(d);
        
        switch(floor.moveCheck(this, d)) {
            case -1:
                vecCandidate.shift();
                return false;
                break;
            case -2://アタック
                vecCandidate.shift();
                return false;
                break;
        }
        
        //移動
        
        vecCandidate.splice(0, vecCandidate.length);
        
        addAction(new Action(2, point.x * 48, point.y * 48, 8 / speed, function():void {  changeDirection(d) } ));
        
        moveGrid(gridX + point.x, gridY + point.y);//グリッドの移動
        
        return true;
    }
    
}

class Action 
{
    public var phase:int;
    public var moveX:int;
    public var moveY:int;
    public var frame:int;
    public var startFunc:Function;
    public var callback:Function;
    
    public function Action(phase:int, moveX:int, moveY:int, frame:int, startFunc:Function = null, callback:Function = null) 
    {
        this.phase = phase;
        this.moveX = moveX / frame;
        this.moveY = moveY / frame;
        this.frame = frame;
        this.startFunc = startFunc;
        this.callback = callback;
        
    }
    
}

class Move 
{
    static private var vecPoint:Vector.<Point> = Vector.<Point>([new Point(0, -1), new Point(1, -1), new Point(1, 0), new Point(1, 1), new Point(0, 1), new Point( -1, 1), new Point( -1, 0), new Point( -1, -1)]);
    
    static public function point(d:int):Point {
        d = fixDirection(d);
        switch(d) {
            case 0:return vecPoint[0]; break;
            case 1:return vecPoint[1]; break;
            case 2:return vecPoint[2]; break;
            case 3:return vecPoint[3]; break;
            case 4:return vecPoint[4]; break;
            case 5:return vecPoint[5]; break;
            case 6:return vecPoint[6]; break;
            case 7:return vecPoint[7]; break;
        }
        return null;
    }
    
    static public function direction(point:Point):int {
        var i:int;
        if (point.x < 0) point.x = -1;
        else if (point.x > 0) point.x = 1;
        else point.x = 0;
        if (point.y < 0) point.y = -1;
        else if (point.y > 0) point.y = 1;
        else point.y = 0;
        for(i = 0; i < 8; i++){
            if (point.x == vecPoint[i].x && point.y == vecPoint[i].y) return i;
        }
        return -1;
    }
    
    static public function fixDirection(d:int):int {
        if (d > 7) d -= 8;
        if (d < 0) d += 8;
        return d;
    }
    
}

class Rand 
{
    
    static public function getInt(n:int, min:int  =  0):int {
        if (n < 0) n = 0;
        return Math.random() * n + min;
    }
    
    static public function minmax(min:int, max:int):int {
        return int(Math.random() * (max - min + 1)) + min;
    }
}

class MiniMap extends Bitmap
{    
    private var size:int = 8;
    
    private const roomColor:uint = 0x669999ff
    
    private var floor:Floor;
    private var ef:EnemyFactory;
    
    public function MiniMap(floor:Floor,ef:EnemyFactory) 
    {
        this.floor = floor;
        this.ef = ef;
        super(new BitmapData(472,280))
        y = 50;
    }
    
    public function newMiniMap():void {
        bitmapData.lock();
        drawFloor();
        drawEnemy();
        bitmapData.unlock();
    }
    
    public function update():void {
        
    }
    
    public function draw():void {
        bitmapData.lock();
        drawFloor();
        drawEnemy();
        bitmapData.unlock();
    }
    
    private function drawFloor():void {
        var i:int, j:int;
        for(i = 0; i < 35; i++)for(j = 0; j < 59; j++){
            var grid:Grid = floor.getGrid(j, i);
            switch(grid.type) {
                case 1:
                case 2:
                    drawRect(j * size, i * size, size, size, roomColor);
                    break;
            }
            
            
        }
    }
    
    private function drawEnemy():void {
        var i:int;
        var enemy:Enemy;
        var len:int;
        if (ef.vecEnemy.length != 0) len = ef.vecEnemy.length;
        for(i = 0; i < len; i++){
            enemy = ef.vecEnemy[i];
            drawRect(enemy.x / 48 * size + 1, enemy.y / 48 * size + 1, size - 2, size - 2, 0xffff0000);
        }
    }
    
    public function drawRect(x:int, y:int, w:int, h:int, fillColor:uint):void {
        bitmapData.fillRect(new Rectangle(x, y, w, h), fillColor);
    }

}

class EnemyFactory
{
    
    public var vecEnemy:Vector.<Enemy>;
    private var floor:Floor;
    
    public function EnemyFactory(floor:Floor) 
    {
        this.floor = floor;
        vecEnemy = new Vector.<Enemy>();
    }
    
    public function update():void {
        var i:int;
        var len:int = vecEnemy.length;
        for(i = 0; i < len; i++){
            vecEnemy[i].update();
        }
    }
    
    public function turnUpdate():void {
        var i:int;
        var len:int = vecEnemy.length;
        
        floor.turn++;
        
        for (i = 0; i < len; i++) {
            vecEnemy[i].turnUpdate();
        }
        
        if (floor.turn % 20 == 1) {
            create();
        }
    }
    
    public function init():void {
        vecEnemy = null;
        vecEnemy = new Vector.<Enemy>();
    }
    
    public function create():void {
        var enemy:Enemy = new Enemy(floor);
        enemy.draw();
        enemy.warp();
        vecEnemy.push(enemy);
    }
    
    public function ready():Boolean {
        var i:int;
        for(i = 0; i < vecEnemy.length; i++){
            if (!vecEnemy[i].ready()) return false;
        }
        return true;
    }
    
    public function removeEnemy(enemy:Enemy):void {
        var i:int;
        var len:int = vecEnemy.length;
        for(i = 0; i < len; i++){
            if (vecEnemy[i] == enemy) {
                vecEnemy.splice(i, 1);
                break;
            }
        }
    }
    
}

class Debug extends Sprite
{
    private var tf:TextField;
    private var time:Number = 0;
    private var cnt:int;
    private var fps:Number = 30;
    
    private var floor:Floor;
    private var ef:EnemyFactory;
    
    public function Debug(floor:Floor,ef:EnemyFactory) 
    {
        this.floor = floor;
        this.ef = ef;
        addChild(tf = new TextField());
        //tf.background = true;
        //tf.backgroundColor = 0xffffff;
        //tf.alpha = 0.5;
    }
    
    public function update():void {
        cnt++;
        getTimer();
        if (getTimer() - time >= 1000) {
            fps = cnt / (getTimer() - time) * 1000;
            cnt = 0;
            time = getTimer();
        }
        tf.text = "";
        tf.appendText("fps:" + int(fps) + "\n");
        tf.appendText("turn " + floor.turn + "\n");
        tf.appendText("enemyNum " + ef.vecEnemy.length + "\n");
    }
    
}