├── static ├── img │ ├── favicon.ico │ ├── chess │ │ ├── chess │ │ │ ├── box.png │ │ │ ├── b_ju.png │ │ │ ├── b_ma.png │ │ │ ├── b_pao.png │ │ │ ├── b_shi.png │ │ │ ├── b_zu.png │ │ │ ├── box2.png │ │ │ ├── r_ju.png │ │ │ ├── r_ma.png │ │ │ ├── r_pao.png │ │ │ ├── r_shi.png │ │ │ ├── r_zu.png │ │ │ ├── b_jiang.png │ │ │ ├── b_xiang.png │ │ │ ├── r_jiang.png │ │ │ └── r_xiang.png │ │ └── board │ │ │ └── board.png │ └── fchess │ │ ├── chess │ │ ├── b.png │ │ ├── w.png │ │ ├── box.png │ │ └── box2.png │ │ └── board │ │ └── board.png └── js │ ├── chess │ ├── chessplayer.js │ ├── chess.js │ ├── fchess.js │ ├── fAI.js │ ├── cchess.js │ └── AI.js │ └── crafty │ └── crafty-min.js ├── readme.md ├── AIAI.html ├── UIUI.html ├── fUIUI.html ├── fUIAI.html ├── UIAI.html ├── end.html └── index.html /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/chess/chess/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/box.png -------------------------------------------------------------------------------- /static/img/fchess/chess/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/fchess/chess/b.png -------------------------------------------------------------------------------- /static/img/fchess/chess/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/fchess/chess/w.png -------------------------------------------------------------------------------- /static/img/chess/board/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/board/board.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_ju.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_ju.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_ma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_ma.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_pao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_pao.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_shi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_shi.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_zu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_zu.png -------------------------------------------------------------------------------- /static/img/chess/chess/box2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/box2.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_ju.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_ju.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_ma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_ma.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_pao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_pao.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_shi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_shi.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_zu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_zu.png -------------------------------------------------------------------------------- /static/img/fchess/board/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/fchess/board/board.png -------------------------------------------------------------------------------- /static/img/fchess/chess/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/fchess/chess/box.png -------------------------------------------------------------------------------- /static/img/fchess/chess/box2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/fchess/chess/box2.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_jiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_jiang.png -------------------------------------------------------------------------------- /static/img/chess/chess/b_xiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/b_xiang.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_jiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_jiang.png -------------------------------------------------------------------------------- /static/img/chess/chess/r_xiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChess/HEAD/static/img/chess/chess/r_xiang.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 中国象棋UI(Javascript离线版) 2 | 3 | 这是一款为了让理查德.狄克.强输得心服口服,无话可说而开发的中国象棋AI。 4 | 5 | ## Demo 6 | 7 | 以下链接使用htmlpreview展示,加载可能会缓慢。 8 | 9 | * 人人对战:[人人对战](http://htmlpreview.github.io/?https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChessUI_Javascript/master/UIUI.html) 10 | * 人机对战:[人机对战](http://htmlpreview.github.io/?https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChessUI_Javascript/master/UIAI.html) 11 | * 机机对战:[观棋不语](http://htmlpreview.github.io/?https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChessUI_Javascript/master/AIAI.html) 12 | * 残局对战:[一虎下山](http://htmlpreview.github.io/?https://raw.githubusercontent.com/JimmyFromSYSU/ChineseChessUI_Javascript/master/end.html) 13 | 14 | 在残局对战中,由AI先手解残局。该残局需要9~10步的棋力才能解开,目前前台AI的棋力只有4步。 15 | -------------------------------------------------------------------------------- /AIAI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 观棋不语 by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /UIUI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIUI by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /fUIUI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIUI by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /fUIAI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UIAI by 南方小智 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /UIAI.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIAI by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /end.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 一虎下山 by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 观棋不语 by 南方小智 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /static/js/chess/chessplayer.js: -------------------------------------------------------------------------------- 1 | 2 | /***********************************\ 3 | * player 模板 4 | \***********************************/ 5 | var Player = { 6 | createNew: function(player_id){ 7 | var player = {}; 8 | player.now_move = false; 9 | player.player_id = player_id; 10 | 11 | player.prepare = function(game){ 12 | } 13 | 14 | player.moveOnce = function(game){ 15 | // save result to game.step.from and game.step.to 16 | // document.dispatchEvent(game.StartMoveEvent); 17 | } 18 | 19 | player.finish = function(winner){ 20 | } 21 | 22 | return player; 23 | } 24 | } 25 | 26 | /***********************************\ 27 | * 中国象棋UI player 28 | \***********************************/ 29 | var UI_Player = { 30 | createNew: function(player_id){ 31 | 32 | var player = Player.createNew(player_id); 33 | 34 | player.flag = false; 35 | 36 | player.prepare = function(game){ 37 | myControl = function(e){ 38 | if(player.now_move == false) return; 39 | if(game.UI_playing == false) return; 40 | 41 | var now = game.getClickPos( {x:e.offsetX, y:e.offsetY}, cell_size/2); 42 | c = game.getChess(now); 43 | // 选择第二颗子 44 | if(player.flag == true){ 45 | if(c && c.player_id == player.player_id){ 46 | game.step.from = now; 47 | game.setChessTo(game.box, now); 48 | } 49 | else{ 50 | game.UI_playing = false; 51 | player.flag = false; 52 | game.step.to = now; 53 | player.now_move = false; 54 | document.dispatchEvent(game.StartMoveEvent); 55 | } 56 | } 57 | // 选择第一颗子 58 | else{ 59 | if(c == null || c.player_id != player.player_id){ 60 | game.hide(game.box); 61 | player.flag = false; 62 | } 63 | else{ 64 | game.step.from = now; 65 | game.setChessTo(game.box, now); 66 | player.flag = true; 67 | } 68 | } 69 | } 70 | 71 | game.sprite.bind('MouseUp', myControl); 72 | }; 73 | 74 | 75 | player.moveOnce = function(game){ 76 | game.UI_playing = true; 77 | player.now_move = true; 78 | player.flag = false; 79 | } 80 | 81 | 82 | player.finish = function(winner){ 83 | game.UI_playing = false; 84 | player.now_move = false; 85 | player.flag = false; 86 | } 87 | 88 | return player; 89 | } 90 | } 91 | 92 | 93 | /***********************************\ 94 | * 中国象棋AI player 95 | \***********************************/ 96 | var AI_Player = { 97 | createNew: function(player_id){ 98 | var player = Player.createNew(player_id); 99 | 100 | player.prepare = function(game){ 101 | player.ai = AI.createNew(); 102 | }; 103 | 104 | player.moveOnce = function(game){ 105 | player.now_move = true; 106 | player.game = game; 107 | initStr = game.toString(); 108 | player.ai.findBestNextStep(initStr,player.player_id, game, player.finishStep); 109 | } 110 | 111 | player.finishStep = function(){ 112 | player.now_move = false; 113 | document.dispatchEvent(player.game.StartMoveEvent); 114 | } 115 | 116 | 117 | player.finish = function(winner){} 118 | 119 | return player; 120 | } 121 | } 122 | 123 | 124 | 125 | /***********************************\ 126 | * 中国象棋网络 player 127 | \***********************************/ 128 | 129 | 130 | //var xhttp = new XMLHttpRequest(); 131 | //xhttp.open("GET", "/compute/", false); 132 | //xhttp.send(); 133 | //document.getElementById("demo").innerHTML = xhttp.responseText; 134 | //console.log(xhttp.responseText); 135 | // 136 | 137 | 138 | /***********************************\ 139 | * 中国象棋网络 player 140 | \***********************************/ 141 | 142 | 143 | //var xhttp = new XMLHttpRequest(); 144 | //xhttp.open("GET", "/compute/", false); 145 | //xhttp.send(); 146 | //document.getElementById("demo").innerHTML = xhttp.responseText; 147 | //console.log(xhttp.responseText); 148 | // 149 | 150 | 151 | /***********************************\ 152 | * 五子棋 UI player 153 | \***********************************/ 154 | var fUI_Player = { 155 | createNew: function(player_id){ 156 | 157 | var player = Player.createNew(player_id); 158 | 159 | player.flag = false; 160 | 161 | player.prepare = function(game){ 162 | myControl = function(e){ 163 | 164 | if(player.now_move == false) return; 165 | if(game.UI_playing == false) return; 166 | 167 | var now = game.getClickPos( {x:e.offsetX, y:e.offsetY}, cell_size/2); 168 | c = game.getChess(now); 169 | if(c == null){ 170 | game.step = {}; 171 | 172 | game.step.player_id = player_id; 173 | game.step.to = now; 174 | 175 | game.UI_playing = false; 176 | player.now_move = false; 177 | if(game.winner.id==-2) 178 | document.dispatchEvent(game.StartMoveEvent); 179 | } 180 | /* 181 | // 选择第二颗子 182 | if(player.flag == true){ 183 | 184 | if(c && c.player_id == player.player_id){ 185 | game.step.from = now; 186 | game.setChessTo(game.box, now); 187 | } 188 | else{ 189 | game.UI_playing = false; 190 | player.flag = false; 191 | game.step.to = now; 192 | player.now_move = false; 193 | document.dispatchEvent(game.StartMoveEvent); 194 | } 195 | } 196 | // 选择第一颗子 197 | else{ 198 | if(c == null || c.player_id != player.player_id){ 199 | game.hide(game.box); 200 | player.flag = false; 201 | } 202 | else{ 203 | game.step.from = now; 204 | game.setChessTo(game.box, now); 205 | player.flag = true; 206 | } 207 | } 208 | */ 209 | } 210 | 211 | game.sprite.bind('MouseUp', myControl); 212 | }; 213 | 214 | 215 | player.moveOnce = function(game){ 216 | game.UI_playing = true; 217 | player.now_move = true; 218 | //player.flag = false; 219 | } 220 | 221 | 222 | player.finish = function(winner){ 223 | game.UI_playing = false; 224 | player.now_move = false; 225 | if(winner.id == player_id){ 226 | alert( (player_id == 0? "黑棋":"白棋") + "赢了!"); 227 | } 228 | } 229 | 230 | return player; 231 | } 232 | } 233 | 234 | /***********************************\ 235 | * 五子棋AI player 236 | \***********************************/ 237 | var fAI_Player = { 238 | createNew: function(player_id){ 239 | var player = Player.createNew(player_id); 240 | 241 | player.prepare = function(game){ 242 | player.ai = fAI.createNew(); 243 | }; 244 | 245 | player.moveOnce = function(game){ 246 | player.now_move = true; 247 | player.game = game; 248 | // 249 | initStr = game.toString(); 250 | player.ai.findBestNextStep(initStr,player.player_id, game, player.finishStep); 251 | } 252 | 253 | player.finishStep = function(){ 254 | player.now_move = false; 255 | if(player.game.winner.id==-2) 256 | document.dispatchEvent(player.game.StartMoveEvent); 257 | } 258 | 259 | 260 | player.finish = function(winner){ 261 | player.now_move = false; 262 | if(winner.id == player_id){ 263 | alert( (player_id == 0? "黑棋":"白棋") + "赢了!"); 264 | } 265 | } 266 | 267 | return player; 268 | } 269 | } 270 | 271 | -------------------------------------------------------------------------------- /static/js/chess/chess.js: -------------------------------------------------------------------------------- 1 | /***********************************\ 2 | * 所有方格棋盘的棋类游戏 3 | * 棋盘中的元素概念介绍: 4 | * game: 整个游戏 5 | * board:棋盘 6 | * chess:棋子 7 | * box:也是chess类,但是代表一个选择框,选定一个棋子 8 | \***********************************/ 9 | 10 | var SquareChessGame = { 11 | createNew: function( 12 | area, 13 | cell_size, cell_img_size, 14 | box_img_size, 15 | b_img_w, b_img_h, 16 | chess_img_size, 17 | img_dir, 18 | bg_color, 19 | b_offset_x, b_offset_y 20 | ) { 21 | 22 | var game = {}; 23 | 24 | /***********************************\ 25 | * 图片文件配置 26 | \***********************************/ 27 | box_img_file = img_dir + "/chess/box.png"; 28 | box2_img_file = img_dir + "/chess/box2.png"; 29 | board_img_file = img_dir + "/board/board.png"; 30 | chess_img_dir = img_dir + "/chess/"; 31 | 32 | /***********************************\ 33 | * 界面元素自适应 34 | \***********************************/ 35 | // 自适应游戏界面 36 | w = b_img_w * cell_size / cell_img_size; 37 | h = b_img_h * cell_size / cell_img_size; 38 | 39 | // 棋子的大小 40 | chess_size = cell_size * 0.95; 41 | 42 | /***********************************\ 43 | * 棋子的隐藏,移动和坐标获取 44 | \***********************************/ 45 | // 隐藏元素到棋盘外 46 | game.hide = function(chess) { 47 | if (chess != null && chess.sprite != null) { 48 | chess.sprite.z = -1; 49 | chess.sprite.x = w + 1; 50 | chess.sprite.y = h + 1; 51 | chess.sprite.tx = w + 1; 52 | chess.sprite.ty = h + 1; 53 | } 54 | } 55 | 56 | // 获取点击位置 57 | game.getClickPos = function(p, bias) { 58 | x = p.x - bias; 59 | y = p.y - bias; 60 | return { 61 | r: Math.floor(y / cell_size), 62 | c: Math.floor(x / cell_size) 63 | } 64 | } 65 | 66 | 67 | // 移动棋子 68 | game.moveChessTo = function(chess, pos) { 69 | if (chess == null || chess.sprite == null) return; 70 | bias_x = (cell_size - chess.sprite.w) / 2 + b_offset_x; 71 | bias_y = (cell_size - chess.sprite.h) / 2 + b_offset_y; 72 | //bias_x = b_offset_x; 73 | //bias_y = b_offset_y; 74 | var p = {}; 75 | p.y = pos.r * cell_size + bias_y; 76 | p.x = pos.c * cell_size + bias_x; 77 | chess.moveTo(p); 78 | } 79 | 80 | // 设置棋子位置,不产生移动动画 81 | game.setChessTo = function(chess, pos) { 82 | if (chess == null || chess.sprite == null) return; 83 | bias_x = (cell_size - chess.sprite.w) / 2 + b_offset_x; 84 | bias_y = (cell_size - chess.sprite.h) / 2 + b_offset_y; 85 | var p = {}; 86 | p.y = pos.r * cell_size + bias_y; 87 | p.x = pos.c * cell_size + bias_x; 88 | chess.setTo(p); 89 | } 90 | 91 | /***********************************\ 92 | * 加载棋盘的接口 93 | \***********************************/ 94 | loadBoard = function() { 95 | Crafty.sprite(board_img_file, { 96 | board: [0, 0, b_img_w, b_img_h] 97 | }); 98 | 99 | game.sprite = Crafty.e("2D, Canvas, board, Mouse").attr({ 100 | x: 0, 101 | y: 0, 102 | z: 0, 103 | w: w, 104 | h: h 105 | }); 106 | 107 | } 108 | 109 | /***********************************\ 110 | * 游戏流程控制 111 | \***********************************/ 112 | // 游戏玩家 113 | var players = []; 114 | getNowPlayer = function(){return players[now_player_cnt];} 115 | game.addPlayer = function(player) { 116 | if(player.length>=2) return; 117 | players.push(player); 118 | } 119 | 120 | /***********************************\ 121 | * 游戏开始的驱动函数 122 | * 当启动第一个下子后,进入事件驱动 123 | \***********************************/ 124 | game.start = function() { 125 | // 无玩家 126 | if (players.length == 0) { 127 | return; 128 | } 129 | // 当前下棋的玩家 130 | now_player_cnt = 0; 131 | 132 | players.forEach(function(p, index) { 133 | p.prepare(game); 134 | }); 135 | 136 | players[now_player_cnt].moveOnce(game); 137 | } 138 | 139 | /***********************************\ 140 | * 游戏结束 141 | \***********************************/ 142 | game.over = function() { 143 | // 可能是玩家当前玩家认输 144 | if(game.winner.id == NOT_GAMEOVER){ 145 | game.winer.id = 1 - game.players[now_player_cnt].player_id; 146 | } 147 | 148 | players.forEach(function(player, index) { 149 | player.finish(game.winner); 150 | }); 151 | now_player_cnt = -1; 152 | } 153 | 154 | /***********************************\ 155 | * 移动棋子 156 | \***********************************/ 157 | game.step = {}; 158 | // [*] 移动棋子的方法需要由子类来定义 159 | game.moveOnce = function(step) {} 160 | 161 | game.startMove = function() { 162 | if(now_player_cnt < 0) return; 163 | if (game.checkMove(game.step, players[now_player_cnt].player_id) == true) { 164 | game.moveOnce(game.step); 165 | } else { 166 | alert("error move: " + game.step); 167 | players[now_player_cnt].moveOnce(game); 168 | } 169 | } 170 | 171 | game.endMove = function() { 172 | game.updateChess(); 173 | if(now_player_cnt < 0) return; 174 | now_player_cnt++; 175 | if (now_player_cnt >= players.length) now_player_cnt = 0; 176 | players[now_player_cnt].moveOnce(game); 177 | game.winner = game.checkWin(); 178 | if (game.winner.id != NOT_GAMEOVER) { 179 | console.log("game over: " + game.winner.id); 180 | document.dispatchEvent(game.GameOverEvent); 181 | } 182 | } 183 | 184 | /***********************************\ 185 | * 定义游戏事件 186 | \***********************************/ 187 | game.GameOverEvent = document.createEvent('Event'); 188 | game.GameOverEvent.initEvent('GameOverEvent', false, false); 189 | game.StartMoveEvent = document.createEvent('Event'); 190 | game.StartMoveEvent.initEvent('StartMoveEvent', false, false); 191 | game.EndMoveEvent = document.createEvent('Event'); 192 | game.EndMoveEvent.initEvent('EndMoveEvent', false, false); 193 | 194 | document.addEventListener("GameOverEvent", game.over, false); 195 | document.addEventListener("StartMoveEvent", game.startMove, false); 196 | document.addEventListener("EndMoveEvent", game.endMove, false); 197 | 198 | /***********************************\ 199 | * [*] 游戏结束和胜负规则接口 200 | \***********************************/ 201 | // 游戏胜者 202 | game.winner = {}; 203 | NOT_GAMEOVER = -2 204 | game.winner.id = NOT_GAMEOVER; 205 | // 检查游戏是否结束,返回一个winner, 206 | // winner.id为胜者, 207 | // =-1:游戏平局 208 | // =-2:游戏尚未结束 209 | game.checkWin = function() { 210 | var winner = {}; 211 | winner.id = -2; 212 | return winner; 213 | } 214 | 215 | /***********************************\ 216 | * [*] 移动规则接口 217 | \***********************************/ 218 | //检查在game的当前状态下,从step.from位置到step.to位置是否合法 219 | game.checkMove = function(step, player_id) { 220 | return true; 221 | } 222 | 223 | 224 | return game; 225 | } 226 | }; 227 | 228 | /***********************************\ 229 | * 棋子 230 | \***********************************/ 231 | var Chess = { 232 | createNew: function(img_size, img_file, size, color, type, player_id, x, y, z, name) { 233 | var chess = {}; 234 | chess.player_id = player_id; 235 | chess.type = type; 236 | chess.color = color; 237 | 238 | function norm(x) { 239 | var max_v = 10; 240 | var min_v = 2; 241 | if (x < 0 && x > -min_v) x = -minv_v; 242 | if (x < -max_v) x = -max_v; 243 | if (x > 0 && x < min_v) x = min_v; 244 | if (x > max_v) x = max_v; 245 | return x; 246 | } 247 | 248 | /***********************************\ 249 | * 棋子移动动画 250 | \***********************************/ 251 | chess.moveAnimation = function() { 252 | chess.sprite.bind('EnterFrame', 253 | function() { 254 | if (this.x != this.tx || this.y != this.ty) { 255 | var speed = 0.3; 256 | this.dx = (this.tx - this.x) * speed; 257 | this.dy = (this.ty - this.y) * speed; 258 | var v = Math.sqrt(this.dx * this.dx + this.dy * this.dy); 259 | var nv = norm(v); 260 | // var nv = 5; 261 | this.dx = this.dx * nv / v; 262 | this.dy = this.dy * nv / v; 263 | 264 | this.z = 2; 265 | if (Math.abs(this.tx - this.x) < Math.abs(this.dx)) { 266 | this.x = this.tx; 267 | this.dx = 0; 268 | } else this.x += this.dx; 269 | 270 | if (Math.abs(this.ty - this.y) < Math.abs(this.dy)) { 271 | this.y = this.ty; 272 | this.dy = 0; 273 | } else this.y += this.dy; 274 | 275 | if (this.x == this.tx && this.y == this.ty) { 276 | document.dispatchEvent(chess.game.EndMoveEvent); 277 | } 278 | } 279 | } 280 | ); 281 | } 282 | 283 | /***********************************\ 284 | * 棋子移动和位置变换 285 | \***********************************/ 286 | chess.moveTo = function(p) { 287 | chess.sprite.tx = p.x; 288 | chess.sprite.ty = p.y; 289 | chess.sprite.z = 1; 290 | } 291 | 292 | chess.setTo = function(p) { 293 | chess.sprite.x = p.x; 294 | chess.sprite.y = p.y; 295 | chess.sprite.tx = p.x; 296 | chess.sprite.ty = p.y; 297 | chess.sprite.z = 1; 298 | } 299 | 300 | /***********************************\ 301 | * 棋子的加载 302 | \***********************************/ 303 | chess.loadChess = function(game) { 304 | 305 | chess.game = game; 306 | 307 | Crafty.sprite(img_file, { 308 | tmp: [0, 0, img_size, img_size] 309 | }); 310 | 311 | chess.sprite = Crafty.e("2D, Canvas, tmp").attr({ 312 | x: x, 313 | y: y, 314 | z: z, 315 | w: size, 316 | h: size, 317 | tx: x, 318 | ty: y, 319 | dx: 0, 320 | dy: 0 321 | }); 322 | 323 | chess.moveAnimation(); 324 | } 325 | 326 | return chess; 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /static/js/chess/fchess.js: -------------------------------------------------------------------------------- 1 | /***********************************\ 2 | * 正常移动规则 3 | \***********************************/ 4 | // 检查位置p是否在左上角为[r,c],大小为(h, w)的矩形区域中 5 | function inRegion(p, l, s) { 6 | if (p.r >= l.r && p.r < l.r + s.h && p.c >= l.c && p.c < l.c + s.w) return true; 7 | else return false; 8 | } 9 | 10 | // 检查在棋盘b中,从p1到p2的最短曼哈顿路径上有多少个棋子,包括p1和p2点 11 | // (如果p1=p2,只计算一次) 12 | // 曼哈顿路径定义为先走斜线,再走直线的一条路径。 13 | function countChess(board, p1, p2) { 14 | var cnt = 0; 15 | var r = p1.r; 16 | var c = p1.c; 17 | 18 | while (r != p2.r || c != p2.c) { 19 | if (board[r][c] != null) cnt++; 20 | if (p2.r > r) r++; 21 | if (p2.r < r) r--; 22 | if (p2.c > c) c++; 23 | if (p2.c < c) c--; 24 | } 25 | 26 | if (board[r][c] != null) cnt++; 27 | 28 | return cnt; 29 | } 30 | 31 | 32 | /***********************************\ 33 | * 五子棋棋游戏 34 | \***********************************/ 35 | var FiveChessGame = { 36 | createNew: function( 37 | area, 38 | cell_size, cell_img_size, 39 | box_img_size, b_img_w, b_img_h, 40 | chess_img_size, img_dir 41 | ) { 42 | 43 | var game = SquareChessGame.createNew( 44 | area, 45 | cell_size, cell_img_size, 46 | box_img_size, b_img_w, b_img_h, 47 | chess_img_size, 48 | img_dir, 49 | bg_color, 50 | 25, 25); 51 | 52 | 53 | /***********************************\ 54 | * 棋盘状态矩阵 55 | \***********************************/ 56 | // 棋网格盘大小 57 | var n_row = 15; 58 | var n_col = 15; 59 | 60 | board = new Array(n_row); 61 | for (var i = 0; i < n_row; i++) { 62 | board[i] = new Array(n_col); 63 | } 64 | 65 | game.getChess = function(pos) { 66 | return board[pos.r][pos.c]; 67 | } 68 | 69 | /***********************************\ 70 | * 棋盘的字符表示 71 | \***********************************/ 72 | game.getChessType = function(c) { 73 | return c; 74 | } 75 | 76 | 77 | game.getChessLetter = function(chess){ 78 | if(chess) { 79 | return chess.type; 80 | } 81 | return '0'; 82 | } 83 | 84 | game.toString = function(){ 85 | var s = ""; 86 | for(var r = 0; r= 0 && p.x < w && p.y >= 0 && p.y < h) { 110 | var now = game.getClickPos(p, cell_size / 2); 111 | if (now.r < 0 || now.r >= n_row) return; 112 | if (now.c < 0 || now.c >= n_col) return; 113 | if(now.r == old_box_pos.r && now.c == old_box_pos.c) return; 114 | old_box_pos = now; 115 | if (game.box2.sprite.z < 0) game.setChessTo(game.box2, now); 116 | else game.setChessTo(game.box2, now); 117 | steps = []; 118 | } 119 | } 120 | 121 | game.fix = function() { 122 | game.moveBoxToMouse = null; 123 | game.hide(game.box1); 124 | game.hide(game.box2); 125 | } 126 | 127 | // 移动棋子 128 | // pre-condition:移动绝对合法,已通过检验 129 | game.moveOnce = function(step) { 130 | //game.setChessTo(game.box, step.to); 131 | //var eat_chess = game.getChess(step.to); 132 | color =(step.player_id==0?'b':'w'); 133 | img_file = chess_img_dir + color + ".png"; 134 | type = color; 135 | r = step.to.r; 136 | c = step.to.c; 137 | new_chess = FiveChess.createNew(chess_img_size, img_file, chess_size, "棋子", type, step.player_id, 0, 0, 1); 138 | board[r][c] = new_chess; 139 | new_chess.loadChess(game); 140 | 141 | game.setChessTo(new_chess, step.to); 142 | 143 | game.setChessTo(game.box, step.to); 144 | 145 | game.updateChess = function(){} 146 | 147 | document.dispatchEvent(game.EndMoveEvent); 148 | 149 | } 150 | 151 | /***********************************\ 152 | * 设置规则检验函数,外部可改变 153 | \***********************************/ 154 | game.checkMove = function(step, player_id) { 155 | if(game.getChess(step.to)) return false; 156 | return true; 157 | //return normalCheck(board, step.from, step.to, player_id); 158 | } 159 | 160 | game.checkWin = function(){ 161 | winner = {}; 162 | winner.id = -2; 163 | for(var r = 0; r< n_row; r++){ 164 | for(var c = 0; c< n_col; c++){ 165 | if(board[r][c]){ 166 | cnt = 1; 167 | while(cnt < 5){ 168 | if(inRegion({r:r,c:c+cnt}, {r:0,c:0}, {w:15,h:15}) 169 | && board[r][c+cnt] && board[r][c+cnt].player_id == board[r][c].player_id){ 170 | cnt++; 171 | } 172 | else break; 173 | } 174 | 175 | if(cnt < 5){ 176 | cnt = 1; 177 | while(cnt < 5){ 178 | if(inRegion({r:r+cnt,c:c}, {r:0,c:0}, {w:15,h:15}) 179 | && board[r+cnt][c] && board[r+cnt][c].player_id == board[r][c].player_id){ 180 | cnt++; 181 | } 182 | else break; 183 | } 184 | } 185 | 186 | if(cnt < 5){ 187 | cnt = 1; 188 | while(cnt < 5){ 189 | if(inRegion({r:r+cnt,c:c+cnt}, {r:0,c:0}, {w:15,h:15}) 190 | && board[r+cnt][c+cnt] && board[r+cnt][c+cnt].player_id == board[r][c].player_id){ 191 | cnt++; 192 | } 193 | else break; 194 | } 195 | } 196 | 197 | if(cnt < 5){ 198 | cnt = 1; 199 | while(cnt < 5){ 200 | if(inRegion({r:r+cnt,c:c-cnt}, {r:0,c:0}, {w:15,h:15}) 201 | && board[r+cnt][c-cnt] && board[r+cnt][c-cnt].player_id == board[r][c].player_id){ 202 | cnt++; 203 | } 204 | else break; 205 | } 206 | } 207 | 208 | 209 | if(cnt == 5){ 210 | winner.id = board[r][c].player_id; 211 | return winner; 212 | } 213 | } 214 | } 215 | } 216 | return winner; 217 | } 218 | 219 | 220 | /***********************************\ 221 | * 初始化棋子位置,加载棋子和棋盘精灵 222 | \***********************************/ 223 | // 大写字母 : player_id = 0, 位于上方 224 | // 小写字母 : player_id = 1, 位于下方 225 | var chessPos = 226 | "000000000000000"+ 227 | "000000000000000"+ 228 | "000000000000000"+ 229 | "000000000000000"+ 230 | "000000000000000"+ 231 | "000000000000000"+ 232 | "000000000000000"+ 233 | "0000000b0000000"+ 234 | "000000000000000"+ 235 | "000000000000000"+ 236 | "000000000000000"+ 237 | "000000000000000"+ 238 | "000000000000000"+ 239 | "000000000000000"+ 240 | "000000000000000"; 241 | 242 | game.setInitPos = function(newPos) { 243 | chessPos = newPos; 244 | } 245 | 246 | game.blackAtTop = true; 247 | 248 | /***********************************\ 249 | * run 250 | \***********************************/ 251 | game.run = function(crafty) { 252 | Crafty.init(w, h, document.getElementById(area)); 253 | /***********************************\ 254 | * board 生成 255 | \***********************************/ 256 | loadBoard(); 257 | game.sprite.bind('MouseMove', game.moveBoxToMouse); 258 | 259 | 260 | /***********************************\ 261 | * box 生成 262 | \***********************************/ 263 | game.box2 = FiveChess.createNew(box_img_size, box2_img_file, chess_size, "选择框", -1, -1, 0, 0, 0); 264 | game.box2.loadChess(game); 265 | game.hide(game.box2); 266 | 267 | game.box = FiveChess.createNew(box_img_size, box_img_file, chess_size, "选择框", -1, -1, 0, 0, 0); 268 | game.box.loadChess(game); 269 | game.hide(game.box); 270 | 271 | /***********************************\ 272 | * 棋子 生成 273 | \***********************************/ 274 | 275 | for (var r = 0; r < n_row; r++) { 276 | for (var c = 0; c < n_col; c++) { 277 | var index = r * n_col + c; 278 | ch = chessPos[index]; 279 | if (ch == 'b') { 280 | player_id = 0; 281 | if (game.blackAtTop) color = 'b'; 282 | else color = 'w'; 283 | } else if (ch == 'w') { 284 | player_id = 1; 285 | if (game.blackAtTop) color = 'w'; 286 | else color = 'b'; 287 | } else continue; 288 | 289 | //type = game.getChessType(ch); 290 | type = color; 291 | img_file = chess_img_dir + color + ".png"; 292 | //img_file = chess_img_dir + color + "_" + type + ".png"; 293 | new_chess = FiveChess.createNew(chess_img_size, img_file, chess_size, "棋子", type, player_id, 0, 0, 1); 294 | board[r][c] = new_chess; 295 | new_chess.loadChess(game); 296 | game.setChessTo(new_chess, { 297 | r: r, 298 | c: c 299 | }); 300 | 301 | } 302 | } 303 | 304 | game.start(); 305 | } 306 | 307 | return game; 308 | } 309 | }; 310 | 311 | 312 | /***********************************\ 313 | * 五子棋子类 314 | \***********************************/ 315 | var FiveChess = { 316 | createNew: function(img_size, img_file, size, color, type, player_id, x, y, z, name) { 317 | var chess = Chess.createNew(img_size, img_file, size, color, type, player_id, x, y, z, name); 318 | return chess; 319 | } 320 | } 321 | 322 | -------------------------------------------------------------------------------- /static/js/chess/fAI.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /***********************************\ 4 | * 游戏AI 5 | \***********************************/ 6 | 7 | var fAI = { 8 | 9 | createNew: function() { 10 | var ai = {}; 11 | var MIN_SCORE = -9999 12 | var MAX_SCORE = 9999; 13 | ai.block = new Array(6); 14 | 15 | getAllPossibleStep= function(board, player_id ){ 16 | steps = []; 17 | for(var r = 0;r<15;r++){ 18 | for(var c = 0; c<15;c++){ 19 | chess = board[r][c]; 20 | if(chess == null && ai.cnt[r][c]>0){ 21 | steps.push( {to:{r:r,c:c}, player_id:player_id } ); // bug: why need player id 22 | } 23 | } 24 | } 25 | return steps; 26 | } 27 | 28 | 29 | ai.evaluateOneBlock = function(now_char){ 30 | var c_now = ai.chess_cnt[now_char]; 31 | var c_next = ai.chess_cnt[now_char=='b'?'w':'b']; 32 | var c_empty = 6-c_now-c_next; 33 | 34 | if(c_now == 6) return MAX_SCORE; 35 | else if(c_now==5){ 36 | if(ai.block[0]!=now_char || ai.block[5]!=now_char) return MAX_SCORE; 37 | else if(c_empty>0) return 1000; // 1 move win 38 | else return 40; // no use 39 | } 40 | else if(c_now==4){ 41 | if(ai.block[0]=='0' && ai.block[5] =='0') return 1000; 42 | return ( c_now - c_next ) * 200; 43 | } 44 | else if(c_now==3){ 45 | return ( c_now - c_next ) * 100; 46 | } 47 | else if(c_now==2){ 48 | return ( c_now - c_next ) * 50; 49 | } 50 | else if(c_now==1){ 51 | return ( c_now - c_next ) * 30; 52 | } 53 | else if(c_now==0){ 54 | return ( c_now - c_next ) * 10; 55 | } 56 | } 57 | 58 | var r_start = [0,0,0,5]; 59 | var r_end = [15,10,10,15]; 60 | var c_start = [0,0,0,0]; 61 | var c_end = [10,15,10,10]; 62 | var dr = [0,1,1,-1]; 63 | var dc = [1,0,1,1]; 64 | 65 | ai.updateScore = function(pos){ 66 | r = pos.r; 67 | c = pos.c; 68 | if(r<0 || r>=15 || c<0 || c>=15) return 0; 69 | var now_c = (ai.root_player_id == 0?'b':'w'); 70 | var score = 0; 71 | var old_score = ai.score[r][c]; 72 | 73 | for(var t = 0;t<4;t++){ 74 | //if(board[r+dr[t]][c+dc[t]] == null) continue; 75 | if(!(r >= r_start[t] && r= c_start[t] && c < c_end[t])) continue; 76 | 77 | ai.chess_cnt = {w:0,b:0,0:0}; 78 | rr = r; 79 | cc = c; 80 | for(var i=0;i<6;i++){ 81 | if(ai.board[rr][cc]) ai.block[i] = ai.board[rr][cc].type; 82 | else ai.block[i] = '0'; 83 | ai.chess_cnt[ai.block[i]] ++; 84 | rr = rr + dr[t] ; 85 | cc = cc + dc[t] ; 86 | } 87 | 88 | score += ai.evaluateOneBlock(now_c); 89 | score -= ai.evaluateOneBlock(now_c=='b'?'w':'b'); 90 | 91 | } 92 | 93 | if(score > MAX_SCORE) score = MAX_SCORE; 94 | if(score < MIN_SCORE) score = MIN_SCORE; 95 | 96 | ai.score[r][c] = score; 97 | return score - old_score; 98 | } 99 | 100 | ai.updateRelatedScore = function(pos, old_chess){ 101 | ai.sum_score += ai.updateScore(pos); 102 | r = pos.r; 103 | c = pos.c; 104 | var now_c = (ai.root_player_id == 0?'b':'w'); 105 | 106 | for(var t = 0;t<4;t++){ 107 | for(var i = 1; i< 6;i++){ 108 | r = pos.r - dr[t] * i; 109 | c = pos.c - dc[t] * i; 110 | if(!(r >= r_start[t] && r= c_start[t] && c < c_end[t])) continue; 111 | 112 | ai.chess_cnt = {w:0,b:0,0:0}; 113 | rr = r; 114 | cc = c; 115 | for(var j=0;j<6;j++){ 116 | if(ai.board[rr][cc]) ai.block[j] = ai.board[rr][cc].type; 117 | else ai.block[j] = '0'; 118 | ai.chess_cnt[ai.block[j]] ++; 119 | rr = rr + dr[t] ; 120 | cc = cc + dc[t] ; 121 | } 122 | 123 | var score = ai.evaluateOneBlock(now_c); 124 | score -= ai.evaluateOneBlock(now_c=='b'?'w':'b'); 125 | 126 | ai.chess_cnt[ai.block[i]] --; 127 | ai.block[i] = old_chess; 128 | ai.chess_cnt[ai.block[i]] ++; 129 | 130 | var old_score = ai.evaluateOneBlock(now_c); 131 | old_score -= ai.evaluateOneBlock(now_c=='b'?'w':'b'); 132 | 133 | var old = ai.score[r][c]; 134 | ai.score[r][c] += score-old_score; 135 | 136 | var now = ai.score[r][c]; 137 | if(now > MAX_SCORE) now = MAX_SCORE; 138 | if(now < MIN_SCORE) now = MIN_SCORE; 139 | ai.score[r][c] = now; 140 | 141 | //ai.sum_score += score-old_score; 142 | ai.sum_score += now-old; 143 | //ai.sum_score += ai.updateScore({r:r,c:c}); 144 | } 145 | } 146 | } 147 | 148 | ai.findBestNextStep = function (initStr, player_id, game, call_back){ 149 | 150 | ai.toString = function(){ 151 | var s = ""; 152 | for(var r = 0; r<15; r++){ 153 | for(var c = 0; c<15; c++){ 154 | s = s + "" + game.getChessLetter(ai.board[r][c]); 155 | } 156 | } 157 | return s; 158 | } 159 | 160 | setTimeout(function(){ 161 | ai.root_player_id = player_id; 162 | ai.strToBoard(initStr,game); 163 | 164 | /***********************************\ 165 | * 极大极小搜索入口 166 | \***********************************/ 167 | ai.deep = 4; 168 | 169 | result = ai.Search(ai.board, player_id, ai.deep, MAX_SCORE+1); 170 | 171 | step = result.step; 172 | 173 | if(step){ 174 | game.step.to = {}; 175 | game.step.to.r = step.to.r; 176 | game.step.to.c = step.to.c; 177 | 178 | game.step.player_id = step.player_id; 179 | 180 | call_back(); 181 | } 182 | }, 100); 183 | 184 | } 185 | 186 | ai.strToBoard = function(initStr,game){ 187 | ai.board = new Array(15); 188 | for (var r = 0; r < 15; r++) { 189 | ai.board[r] = new Array(15); 190 | } 191 | 192 | ai.cnt = new Array(15); 193 | for (var r = 0; r < 15; r++) { 194 | ai.cnt[r] = new Array(15); 195 | for(var c = 0; c<15; c++) ai.cnt[r][c] = 0; 196 | } 197 | 198 | ai.score = new Array(15); 199 | ai.sum_score = 0; 200 | for (var r = 0; r < 15; r++) { 201 | ai.score[r] = new Array(15); 202 | for(var c = 0; c<15; c++){ 203 | ai.score[r][c] = 0; 204 | } 205 | } 206 | 207 | 208 | ai.d = 1; 209 | 210 | index = 0; 211 | for(var r = 0; r<15;r++){ 212 | for(var c = 0; c<15;c++){ 213 | ch = initStr[index]; 214 | if(ch!='0'){ 215 | chess = {}; 216 | chess.player_id = (ch=='b'?0:1); 217 | chess.type = game.getChessType(ch); 218 | ai.board[r][c] = chess; 219 | 220 | ai.cnt[r][c] = -1; 221 | for(var tr = r-ai.d; tr<=r+ai.d; tr++){ 222 | for(var tc = c-ai.d; tc<=c+ai.d; tc++){ 223 | if(tr >= 0 && tr < 15 && tc >=0 && tc < 15){ 224 | if(ai.cnt[tr][tc]>=0){ 225 | ai.cnt[tr][tc]++; 226 | } 227 | } 228 | } 229 | } 230 | } 231 | index ++; 232 | } 233 | } 234 | 235 | 236 | for (var r = 0; r < 15; r++) { 237 | for(var c = 0; c<15; c++){ 238 | ai.sum_score += ai.updateScore({r:r,c:c}); 239 | } 240 | } 241 | //console.log("initial sum: " + ai.sum_score); 242 | //var s = ""; for(var a=0;a<15;a++){for(var b=0;b<15;b++){s += ai.score[a][b]+" ";} s+="\n";} console.log(s); 243 | } 244 | 245 | 246 | ai.Search = function(board, player_id, deep, now_best){ 247 | var flag = (player_id != ai.root_player_id?true:false); 248 | 249 | var steps = getAllPossibleStep(board, player_id); 250 | //console.log("size of steps: " + steps.length); 251 | 252 | move = function(board, step){ 253 | chess = {}; 254 | chess.player_id = step.player_id; 255 | chess.type = (step.player_id==0?'b':'w'); 256 | r = step.to.r; 257 | c = step.to.c; 258 | board[r][c] = chess; 259 | ai.cnt[r][c] = -1; 260 | 261 | for(var tr = r-ai.d; tr<=r+ai.d; tr++){ 262 | for(var tc = c-ai.d; tc<=c+ai.d; tc++){ 263 | if(tr >= 0 && tr < 15 && tc >=0 && tc < 15){ 264 | if(ai.cnt[tr][tc]>=0){ 265 | ai.cnt[tr][tc]++; 266 | } 267 | } 268 | } 269 | } 270 | ai.updateRelatedScore(step.to, '0'); 271 | // console.log("after move "+ deep +": " + ai.sum_score); 272 | // console.log(step.to.r + " " + step.to.c); 273 | // var s = ""; for(var a=0;a<15;a++){for(var b=0;b<15;b++){s += ai.score[a][b]+" ";} s+="\n";} console.log(s); 274 | } 275 | 276 | unmove = function(board, step){ 277 | r = step.to.r; 278 | c = step.to.c; 279 | old_chess = board[r][c].type; 280 | board[r][c] = null; 281 | 282 | for(var tr = r-ai.d; tr<=r+ai.d; tr++){ 283 | for(var tc = c-ai.d; tc<=c+ai.d; tc++){ 284 | if(tr >= 0 && tr < 15 && tc >=0 && tc < 15){ 285 | if(ai.cnt[tr][tc]>=0){ 286 | ai.cnt[tr][tc]--; 287 | } 288 | } 289 | } 290 | } 291 | 292 | ai.cnt[r][c] = 0; 293 | 294 | for(var tr = r-ai.d; tr<=r+ai.d; tr++){ 295 | for(var tc = c-ai.d; tc<=c+ai.d; tc++){ 296 | if(tr >= 0 && tr < 15 && tc >=0 && tc < 15){ 297 | if(ai.cnt[tr][tc]<0){ 298 | ai.cnt[r][c]++; 299 | } 300 | } 301 | } 302 | } 303 | 304 | ai.updateRelatedScore(step.to, old_chess); 305 | 306 | //console.log("after unmove "+ deep +": " + ai.sum_score); 307 | //console.log(step.to.r + " " + step.to.c); 308 | //var s = ""; for(var a=0;a<15;a++){for(var b=0;b<15;b++){s += ai.score[a][b]+" ";} s+="\n";} console.log(s); 309 | } 310 | 311 | var best_id = 0; 312 | 313 | var best_score = MIN_SCORE; 314 | 315 | if(flag) best_score = MAX_SCORE; 316 | 317 | for(var id = 0; id < steps.length; id++){ 318 | 319 | //console.log(steps[id].to.r + " " + steps[id].to.c); 320 | 321 | /***********************************\ 322 | * 更新节点值 323 | \***********************************/ 324 | move(board, steps[id]); 325 | if(deep==1){ 326 | //score = ai.evaluate(board, player_id); 327 | score = ai.sum_score; 328 | } 329 | else { 330 | //score = ai.evaluate(board, player_id); 331 | score = ai.sum_score; 332 | if(Math.abs(score) < 9000){ 333 | result = ai.Search(ai.board, 1-player_id, deep-1, best_score); 334 | score = result.score; 335 | } 336 | } 337 | unmove(board, steps[id]); 338 | 339 | /***********************************\ 340 | * 更新最优走法 341 | \***********************************/ 342 | 343 | //if( (!flag && score > best_score) || (flag && score < best_score)){ 344 | if( (!flag && score >= best_score) || (flag && score <= best_score)){ 345 | if(!(Math.abs(score - best_score) == 0 && Math.floor((Math.random() * 3)) == 0)){ 346 | best_id = id; 347 | best_score = score; 348 | } 349 | } 350 | 351 | /***********************************\ 352 | * a-b 剪子 353 | \***********************************/ 354 | if(flag && now_best > best_score) { 355 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 356 | return result; 357 | } 358 | 359 | else if(!flag && now_best < best_score){ 360 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 361 | return result; 362 | } 363 | } 364 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 365 | return result; 366 | } 367 | 368 | /* 369 | 370 | ai.evaluate = function(board, last_player_id){ 371 | 372 | var now_c = (ai.root_player_id == 0?'b':'w'); 373 | var score = 0; 374 | //var now_w = 1; 375 | //var next_w = 0.95; 376 | 377 | 378 | for(var t = 0;t<4;t++){ 379 | for(var r = r_start[t]; r MAX_SCORE) score = MAX_SCORE; 402 | if(score < MIN_SCORE) score = MIN_SCORE; 403 | //console.log("final score: " + score); 404 | return score; 405 | } 406 | */ 407 | return ai; 408 | } 409 | } 410 | 411 | -------------------------------------------------------------------------------- /static/js/chess/cchess.js: -------------------------------------------------------------------------------- 1 | /***********************************\ 2 | * 正常移动规则 3 | \***********************************/ 4 | // 检查位置p是否在左上角为[r,c],大小为(h, w)的矩形区域中 5 | function inRegion(p, l, s) { 6 | if (p.r >= l.r && p.r < l.r + s.h && p.c >= l.c && p.c < l.c + s.w) return true; 7 | else return false; 8 | } 9 | 10 | // 检查在棋盘b中,从p1到p2的最短曼哈顿路径上有多少个棋子,包括p1和p2点 11 | // (如果p1=p2,只计算一次) 12 | // 曼哈顿路径定义为先走斜线,再走直线的一条路径。 13 | function countChess(board, p1, p2) { 14 | var cnt = 0; 15 | var r = p1.r; 16 | var c = p1.c; 17 | 18 | while (r != p2.r || c != p2.c) { 19 | if (board[r][c] != null) cnt++; 20 | if (p2.r > r) r++; 21 | if (p2.r < r) r--; 22 | if (p2.c > c) c++; 23 | if (p2.c < c) c--; 24 | } 25 | 26 | if (board[r][c] != null) cnt++; 27 | 28 | return cnt; 29 | } 30 | 31 | //给一个棋盘,检查是否能将在[old_row, old_col]当中的棋子移动到[new_row,new_col]作为合法的一步。 32 | function normalCheck(board, old, now, player_id) { 33 | // 自己走向自己非法 34 | if (old.r == now.r && old.c == now.c) return false; 35 | 36 | // 边界越界 37 | if (!inRegion(old, { 38 | r: 0, 39 | c: 0 40 | }, { 41 | h: 10, 42 | w: 9 43 | })) return false; 44 | if (!inRegion(now, { 45 | r: 0, 46 | c: 0 47 | }, { 48 | h: 10, 49 | w: 9 50 | })) return false; 51 | 52 | var s = board[old.r][old.c]; 53 | var t = board[now.r][now.c]; 54 | var cnt = countChess(board, now, old); 55 | 56 | // 起点没有棋子或是对方的子。 57 | if (s == null) return false; 58 | if(s.player_id != player_id) retur 59 | 60 | // 路障太多 61 | if (cnt > 3) return false; 62 | 63 | 64 | // 吃到自己的子 65 | if (t != null && s.player_id == t.player_id) return false; 66 | 67 | // dx dy 有向距离 68 | // x y 无向距离 69 | var dr = now.r - old.r; 70 | var dc = now.c - old.c; 71 | var r = dr > 0 ? dr : -dr; 72 | var c = dc > 0 ? dc : -dc; 73 | 74 | if (s.type == "jiang") { 75 | if (s.player_id == 0 && !(inRegion(now, { 76 | r: 0, 77 | c: 3 78 | }, { 79 | h: 3, 80 | w: 3 81 | }))) return false; 82 | if (s.player_id == 1 && !(inRegion(now, { 83 | r: 7, 84 | c: 3 85 | }, { 86 | h: 3, 87 | w: 3 88 | }))) return false; 89 | if (!((r == 1 && c == 0) || (r == 0 && c == 1))) 90 | return false; 91 | } else if (s.type == "ju") { 92 | if (r != 0 && c != 0) return false; 93 | if (cnt > 2) return false; 94 | if (cnt == 2 && t == null) return false; 95 | } else if (s.type == "pao") { 96 | if (r != 0 && c != 0) return false; 97 | if (cnt == 3 && t == null) return false; 98 | if (cnt == 2) return false; 99 | } else if (s.type == "ma") { 100 | if (!((r == 1 && c == 2) || (r == 2 && c == 1))) return false; 101 | if (cnt > 2) return false; 102 | if (cnt == 2 && t == null) return false; 103 | } else if (s.type == "shi") { 104 | if (s.player_id == 0 && !(inRegion(now, { 105 | r: 0, 106 | c: 3 107 | }, { 108 | h: 3, 109 | w: 3 110 | }))) return false; 111 | if (s.player_id == 1 && !(inRegion(now, { 112 | r: 7, 113 | c: 3 114 | }, { 115 | h: 3, 116 | w: 3 117 | }))) return false; 118 | if (!(r == 1 && c == 1)) return false; 119 | } else if (s.type == "xiang") { 120 | // region 121 | if (s.player_id == 0 && !(inRegion(now, { 122 | r: 0, 123 | c: 0 124 | }, { 125 | h: 5, 126 | w: 9 127 | }))) return false; 128 | if (s.player_id == 1 && !(inRegion(now, { 129 | r: 5, 130 | c: 0 131 | }, { 132 | h: 5, 133 | w: 9 134 | }))) return false; 135 | 136 | if (!(r == 2 && c == 2)) return false; 137 | if (cnt > 2) return false; 138 | if (cnt == 2 && t == null) return false; 139 | } else if (s.type == "zu") { 140 | if (s.player_id == 0 && dr < 0) return false; 141 | if (s.player_id == 1 && dr > 0) return false; 142 | 143 | if (s.player_id == 0 && inRegion(now, { 144 | r: 0, 145 | c: 0 146 | }, { 147 | h: 5, 148 | w: 9 149 | })) { 150 | if (c != 0) return false; 151 | if (r != 1) return false; 152 | } else { 153 | if (!((r == 0 && c == 1) || (r == 1 && c == 0))) return false; 154 | } 155 | 156 | if (s.player_id == 1 && inRegion(now, { 157 | r: 5, 158 | c: 0 159 | }, { 160 | h: 5, 161 | w: 9 162 | })) { 163 | if (c != 0) return false; 164 | if (r != 1) return false; 165 | } else { 166 | if (!((r == 0 && c == 1) || (r == 1 && c == 0))) return false; 167 | } 168 | } 169 | return true; 170 | } 171 | 172 | 173 | /***********************************\ 174 | * 中国象棋游戏 175 | \***********************************/ 176 | var ChineseChessGame = { 177 | createNew: function( 178 | area, 179 | cell_size, cell_img_size, 180 | box_img_size, b_img_w, b_img_h, 181 | chess_img_size, img_dir 182 | ) { 183 | 184 | var game = SquareChessGame.createNew( 185 | area, 186 | cell_size, cell_img_size, 187 | box_img_size, b_img_w, b_img_h, 188 | chess_img_size, 189 | img_dir, 190 | bg_color, 191 | cell_size / 2, cell_size / 2); 192 | 193 | 194 | /***********************************\ 195 | * 棋盘状态矩阵 196 | \***********************************/ 197 | // 棋网格盘大小 198 | var n_row = 10; 199 | var n_col = 9; 200 | board = new Array(n_row); 201 | for (var i = 0; i < n_row; i++) { 202 | board[i] = new Array(n_col); 203 | } 204 | game.getChess = function(pos) { 205 | return board[pos.r][pos.c]; 206 | } 207 | 208 | /***********************************\ 209 | * 棋盘的字符表示 210 | \***********************************/ 211 | game.getChessType = function(c) { 212 | if (c == 'j' || c == 'J') return "ju"; 213 | if (c == 'm' || c == 'M') return "ma"; 214 | if (c == 'x' || c == 'X') return "xiang"; 215 | if (c == 's' || c == 'S') return "shi"; 216 | if (c == 'k' || c == 'K') return "jiang"; 217 | if (c == 'p' || c == 'P') return "pao"; 218 | if (c == 'z' || c == 'Z') return "zu"; 219 | } 220 | 221 | game.getChessLetter = function(chess){ 222 | if(chess) { 223 | var type = chess.type; 224 | if(type == "ju") return chess.player_id == 0? 'J':'j'; 225 | if(type == "ma") return chess.player_id == 0? 'M':'m'; 226 | if(type == "xiang") return chess.player_id == 0? 'X':'x'; 227 | if(type == "shi") return chess.player_id == 0? 'S':'s'; 228 | if(type == "jiang") return chess.player_id == 0? 'K':'k'; 229 | if(type == "pao") return chess.player_id == 0? 'P':'p'; 230 | if(type == "zu") return chess.player_id == 0? 'Z':'z'; 231 | } 232 | return '0'; 233 | } 234 | 235 | game.toString = function(){ 236 | var s = ""; 237 | for(var r = 0; r= 0 && p.x < w && p.y >= 0 && p.y < h) { 259 | var now = game.getClickPos(p, cell_size / 2); 260 | if (now.r < 0 || now.r >= n_row) return; 261 | if (now.c < 0 || now.c >= n_col) return; 262 | if(now.r == old_box_pos.r && now.c == old_box_pos.c) return; 263 | old_box_pos = now; 264 | if (game.box2.sprite.z < 0) game.setChessTo(game.box2, now); 265 | else game.setChessTo(game.box2, now); 266 | steps = []; 267 | // getPossibleStep(board, now, steps); 268 | // steps.forEach(function(step, index){ 269 | // console.log(step.to.r + " " + step.to.c); 270 | // }); 271 | 272 | } 273 | } 274 | 275 | game.fix = function() { 276 | game.moveBoxToMouse = null; 277 | game.hide(game.box1); 278 | game.hide(game.box2); 279 | } 280 | 281 | // 移动棋子 282 | // pre-condition:移动绝对合法,已通过检验 283 | game.moveOnce = function(step) { 284 | game.setChessTo(game.box, step.to); 285 | var eat_chess = game.getChess(step.to); 286 | 287 | game.updateChess = function() { 288 | game.hide(eat_chess); 289 | tmp_chess.sprite.z = 1; 290 | } 291 | 292 | var tmp_chess = game.getChess(step.from); 293 | 294 | game.moveChessTo(tmp_chess, step.to); 295 | 296 | board[step.from.r][step.from.c] = null; 297 | board[step.to.r][step.to.c] = tmp_chess; 298 | } 299 | 300 | /***********************************\ 301 | * 设置规则检验函数,外部可改变 302 | \***********************************/ 303 | game.checkMove = function(step, player_id) { 304 | return normalCheck(board, step.from, step.to, player_id); 305 | } 306 | 307 | game.checkWin = function(){ 308 | winner = {}; 309 | winner.id = -2; 310 | 311 | flag0 = false; 312 | flag1 = false; 313 | kpos = {}; 314 | Kpos = {} 315 | for(var r = 0; r < n_row; r++){ 316 | for(var c = 0; c < n_col; c++){ 317 | if(board[r][c] && board[r][c].type=="jiang"){ 318 | if(board[r][c].player_id== 0){ 319 | flag0 = true; 320 | Kpos = {r:r, c:c}; 321 | } 322 | if(board[r][c].player_id== 1){ 323 | flag1 = true; 324 | kpos = {r:r, c:c}; 325 | } 326 | } 327 | } 328 | } 329 | 330 | // 将帅见面,谁刚走谁输 331 | 332 | if(flag0 == false && flag1== false) winner.id = -1; 333 | else if(flag0 == false) winner.id = 1; 334 | else if(flag1 == false) winner.id = 0; 335 | else{ 336 | if(Kpos.c == kpos.c){ 337 | if(countChess(board, kpos, Kpos)==2 ){ 338 | if(getNowPlayer().player_id==0) winner.id = 1; 339 | else if(getNowPlayer().player_id==1) winner.id = 0; 340 | } 341 | } 342 | } 343 | return winner; 344 | } 345 | 346 | 347 | /***********************************\ 348 | * 初始化棋子位置,加载棋子和棋盘精灵 349 | \***********************************/ 350 | // 大写字母 : player_id = 0, 位于上方 351 | // 小写字母 : player_id = 1, 位于下方 352 | var chessPos = 353 | "JMXSKSXMJ" + 354 | "000000000" + 355 | "0P00000P0" + 356 | "Z0Z0Z0Z0Z" + 357 | "000000000" + 358 | "000000000" + 359 | "z0z0z0z0z" + 360 | "0p00000p0" + 361 | "000000000" + 362 | "jmxsksxmj"; 363 | 364 | game.setInitPos = function(newPos) { 365 | chessPos = newPos; 366 | } 367 | 368 | game.blackAtTop = true; 369 | 370 | /***********************************\ 371 | * run 372 | \***********************************/ 373 | game.run = function(crafty) { 374 | Crafty.init(w, h, document.getElementById(area)); 375 | /***********************************\ 376 | * board 生成 377 | \***********************************/ 378 | loadBoard(); 379 | game.sprite.bind('MouseMove', game.moveBoxToMouse); 380 | 381 | 382 | /***********************************\ 383 | * box 生成 384 | \***********************************/ 385 | game.box2 = ChineseChess.createNew(box_img_size, box2_img_file, chess_size, "选择框", -1, -1, 0, 0, 0); 386 | game.box2.loadChess(game); 387 | game.hide(game.box2); 388 | 389 | game.box = ChineseChess.createNew(box_img_size, box_img_file, chess_size, "选择框", -1, -1, 0, 0, 0); 390 | game.box.loadChess(game); 391 | game.hide(game.box); 392 | 393 | /***********************************\ 394 | * 棋子 生成 395 | \***********************************/ 396 | for (var r = 0; r < n_row; r++) { 397 | for (var c = 0; c < n_col; c++) { 398 | var index = r * n_col + c; 399 | ch = chessPos[index]; 400 | if (ch >= 'A' && ch <= 'Z') { 401 | player_id = 0; 402 | if (game.blackAtTop) color = 'b'; 403 | else color = 'r'; 404 | } else if (ch >= 'a' && ch <= 'z') { 405 | player_id = 1; 406 | if (game.blackAtTop) color = 'r'; 407 | else color = 'b'; 408 | } else continue; 409 | 410 | type = game.getChessType(ch); 411 | img_file = chess_img_dir + color + "_" + type + ".png"; 412 | new_chess = ChineseChess.createNew(chess_img_size, img_file, chess_size, "棋子", type, player_id, 0, 0, 1); 413 | board[r][c] = new_chess; 414 | new_chess.loadChess(game); 415 | game.setChessTo(new_chess, { 416 | r: r, 417 | c: c 418 | }); 419 | 420 | } 421 | } 422 | 423 | game.start(); 424 | } 425 | 426 | return game; 427 | } 428 | }; 429 | 430 | 431 | /***********************************\ 432 | * 象棋棋子类 433 | \***********************************/ 434 | var ChineseChess = { 435 | createNew: function(img_size, img_file, size, color, type, player_id, x, y, z, name) { 436 | var chess = Chess.createNew(img_size, img_file, size, color, type, player_id, x, y, z, name); 437 | return chess; 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /static/js/chess/AI.js: -------------------------------------------------------------------------------- 1 | /***********************************\ 2 | * 获取所有移动可能 3 | * board所代表的局面必须合法 4 | \***********************************/ 5 | getPossibleStepFrom = function(board, from, steps){ 6 | // 边界越界 7 | if (!inRegion(from, { 8 | r: 0, 9 | c: 0 10 | }, { 11 | h: 10, 12 | w: 9 13 | })) return; 14 | 15 | var s = board[from.r][from.c]; 16 | if (s == null) return; 17 | 18 | dir_plus= [{dr:0,dc:1},{dr:0,dc:-1},{dr:1,dc:0},{dr:-1,dc:0}]; 19 | dir_cross = [{dr:1,dc:1},{dr:1,dc:-1},{dr:-1,dc:1},{dr:-1,dc:-1}]; 20 | dir_cross2 = [{dr:2,dc:2},{dr:2,dc:-2},{dr:-2,dc:2},{dr:-2,dc:-2}]; 21 | dir_jump = [{dr:1,dc:2},{dr:1,dc:-2},{dr:2,dc:1},{dr:-2,dc:1},{dr:-1,dc:2},{dr:-1,dc:-2},{dr:2,dc:-1},{dr:-2,dc:-1}]; 22 | 23 | checkToPosition = function(to, region, must_eat){ 24 | if (!inRegion(to, region.rc, region.hw)) return false; 25 | to_chess = board[to.r][to.c]; 26 | if(to_chess){ 27 | if(to_chess.player_id == s.player_id) return false; 28 | } 29 | else if(must_eat) return false; 30 | return true; 31 | } 32 | getBlockDir = function(dir){ 33 | return {dr: dir.dr > 0? dir.dr-1:dir.dr+1,dc: dir.dc > 0? dir.dc-1: dir.dc+1}; 34 | } 35 | if (s.type == "jiang") { 36 | dir_plus.forEach(function(dir,index){ 37 | var to = {}; 38 | to.r = from.r + dir.dr; 39 | to.c = from.c + dir.dc; 40 | if(s.player_id == 0) region = {rc:{r:0,c:3},hw:{h:3,w:3}}; 41 | else if(s.player_id == 1) region = {rc:{r:7,c:3},hw:{h:3,w:3}}; 42 | if(checkToPosition(to, region,false)){ 43 | steps.push({from:from, to:to}); 44 | } 45 | }); 46 | } else if (s.type == "ju") { 47 | dir_plus.forEach(ju_pos = function(dir,index){ 48 | flag = true; 49 | var dis = 1; 50 | while(flag){ 51 | var to = {}; 52 | to.r = from.r + dir.dr * dis; 53 | to.c = from.c + dir.dc * dis; 54 | region = {rc:{r:0,c:0},hw:{h:10,w:9}}; 55 | if(checkToPosition(to, region,false)){ 56 | steps.push({from:from, to:to}); 57 | if(board[to.r][to.c]) flag = false; 58 | } 59 | else flag = false; 60 | dis ++; 61 | } 62 | }); 63 | } else if (s.type == "pao") { 64 | dir_plus.forEach(ju_pos = function(dir,index){ 65 | cnt = 0; 66 | var dis = 1; 67 | while(cnt<2){ 68 | var to = {}; 69 | to.r = from.r + dir.dr * dis; 70 | to.c = from.c + dir.dc * dis; 71 | region = {rc:{r:0,c:0},hw:{h:10,w:9}}; 72 | 73 | if (inRegion(to, region.rc, region.hw)) 74 | { 75 | to_chess = board[to.r][to.c]; 76 | if(cnt == 0 && !to_chess) steps.push({from:from, to:to}); 77 | if(cnt == 1 && to_chess && to_chess.player_id != s.player_id) steps.push({from:from, to:to}); 78 | if(to_chess) cnt ++ ; 79 | } 80 | else { cnt = 3;} 81 | dis ++; 82 | } 83 | }); 84 | 85 | } else if (s.type == "ma") { 86 | dir_jump.forEach(function(dir,index){ 87 | var to = {}; 88 | to.r = from.r + dir.dr; 89 | to.c = from.c + dir.dc; 90 | b_dir = getBlockDir(dir); 91 | block = {}; 92 | block.r = from.r + b_dir.dr; 93 | block.c = from.c + b_dir.dc; 94 | region = {rc:{r:0,c:0},hw:{h:10,w:9}}; 95 | if(checkToPosition(to, region,false)){ 96 | if(!board[block.r][block.c]) 97 | steps.push({from:from, to:to}); 98 | } 99 | }); 100 | } else if (s.type == "shi") { 101 | dir_cross.forEach(function(dir,index){ 102 | var to = {}; 103 | to.r = from.r + dir.dr; 104 | to.c = from.c + dir.dc; 105 | if(s.player_id == 0) region = {rc:{r:0,c:3},hw:{h:3,w:3}}; 106 | else if(s.player_id == 1) region = {rc:{r:7,c:3},hw:{h:3,w:3}}; 107 | if(checkToPosition(to, region,false)){ 108 | steps.push({from:from, to:to}); 109 | } 110 | }); 111 | } else if (s.type == "xiang") { 112 | dir_cross2.forEach(function(dir,index){ 113 | var to = {}; 114 | to.r = from.r + dir.dr; 115 | to.c = from.c + dir.dc; 116 | b_dir = getBlockDir(dir); 117 | block = {}; 118 | block.r = from.r + b_dir.dr; 119 | block.c = from.c + b_dir.dc; 120 | if(s.player_id == 0) region = {rc:{r:0,c:0},hw:{h:5,w:9}}; 121 | else if(s.player_id == 1) region = {rc:{r:5,c:0},hw:{h:5,w:9}}; 122 | if(checkToPosition(to, region,false)){ 123 | if(!board[block.r][block.c]) 124 | steps.push({from:from, to:to}); 125 | } 126 | }); 127 | } else if (s.type == "zu") { 128 | dir_plus.forEach(function(dir,index){ 129 | var to = {}; 130 | var flag = true; 131 | to.r = from.r + dir.dr; 132 | to.c = from.c + dir.dc; 133 | 134 | if (s.player_id == 0 && dir.dr < 0) flag=false; 135 | if (s.player_id == 1 && dir.dr > 0) flag=false; 136 | 137 | r = dir.dr>0?dir.dr:-dir.dr; 138 | c = dir.dc>0?dir.dc:-dir.dc; 139 | 140 | if (s.player_id == 0 && inRegion(from, {r: 0,c: 0}, {h: 5,w: 9})) { 141 | if (dir.dc != 0) flag=false; 142 | } else { 143 | if (!((r == 0 && c == 1) || (r == 1 && c == 0))) flag=false; 144 | } 145 | 146 | if (s.player_id == 1 && inRegion(from, {r: 5,c: 0}, {h: 5,w: 9})) { 147 | if (dir.dc != 0) flag=false; 148 | } else { 149 | if (!((r == 0 && c == 1) || (r == 1 && c == 0))) flag=false; 150 | } 151 | 152 | region = {rc:{r:0,c:0},hw:{h:10,w:9}}; 153 | if(flag && checkToPosition(to, region,false)){ 154 | steps.push({from:from, to:to}); 155 | } 156 | }); 157 | } 158 | } 159 | 160 | getAllPossibleStep= function(board, player_id ){ 161 | steps = []; 162 | for(var r = 0;r<10;r++){ 163 | for(var c = 0; c<9;c++){ 164 | chess = board[r][c]; 165 | if(chess && chess.player_id == player_id){ 166 | getPossibleStepFrom(board, {r:r,c:c}, steps); 167 | } 168 | } 169 | } 170 | return steps; 171 | } 172 | 173 | /***********************************\ 174 | * 游戏AI 175 | \***********************************/ 176 | 177 | var AI = { 178 | 179 | createNew: function() { 180 | var ai = {}; 181 | var MIN_SCORE = -9999 182 | var MAX_SCORE = 9999; 183 | 184 | //console.log("create ------------------------"); 185 | 186 | 187 | ai.findBestNextStep = function (initStr, player_id, game, call_back){ 188 | 189 | ai.toString = function(){ 190 | var s = ""; 191 | for(var r = 0; r<10; r++){ 192 | for(var c = 0; c<9; c++){ 193 | s = s + "" + game.getChessLetter(ai.board[r][c]); 194 | } 195 | } 196 | return s; 197 | } 198 | 199 | ai.set = {}; 200 | setTimeout(function(){ 201 | //console.log(initStr); 202 | ai.myplayer_id = player_id; 203 | ai.strToBoard(initStr,game); 204 | /***********************************\ 205 | * 极大极小搜索入口 206 | \***********************************/ 207 | ai.deep = 4; 208 | ai.eatStack = []; 209 | result = ai.Search(ai.board, player_id, ai.deep, MAX_SCORE+1); 210 | step = result.step; 211 | if(step){ 212 | // 213 | console.log(result.score + " from: " + step.from.r + " " + step.from.c + 214 | " to: " + step.to.r + " " + step.to.c); 215 | game.step.from = {}; 216 | game.step.to = {}; 217 | game.step.from.r = step.from.r; 218 | game.step.from.c = step.from.c; 219 | game.step.to.r = step.to.r; 220 | game.step.to.c = step.to.c; 221 | 222 | call_back(); 223 | } 224 | }, 10); 225 | 226 | } 227 | 228 | ai.strToBoard = function(initStr,game){ 229 | ai.board = new Array(10); 230 | for (var r = 0; r < 10; r++) { 231 | ai.board[r] = new Array(9); 232 | } 233 | 234 | index = 0; 235 | //console.log("------------------------"); 236 | for(var r = 0; r<10;r++){ 237 | for(var c = 0; c<9;c++){ 238 | ch = initStr[index]; 239 | if(ch!='0'){ 240 | chess = {}; 241 | chess.player_id = ((ch>='A' &&ch<='Z')?0:1); 242 | chess.type = game.getChessType(ch); 243 | ai.board[r][c] = chess; 244 | } 245 | index ++; 246 | } 247 | } 248 | } 249 | 250 | ai.eatStack = []; 251 | 252 | ai.Search = function(board, player_id, deep, now_best){ 253 | //var b_str = ai.toString(); 254 | //result = ai.set[b_str] 255 | //if(result) return result; 256 | 257 | // 258 | //console.log("ai belong to: " + ai.myplayer_id+ " player_id: "+ player_id + " deep: " + deep); 259 | var flag = (player_id != ai.myplayer_id?true:false); 260 | 261 | var steps = getAllPossibleStep(board, player_id); 262 | 263 | move = function(board, step){ 264 | ai.eatStack.push(board[step.to.r][step.to.c]); 265 | board[step.to.r][step.to.c] = board[step.from.r][step.from.c]; 266 | board[step.from.r][step.from.c] = null; 267 | } 268 | 269 | unmove = function(board, step){ 270 | board[step.from.r][step.from.c] = board[step.to.r][step.to.c]; 271 | board[step.to.r][step.to.c] = ai.eatStack.pop(); 272 | } 273 | 274 | var best_id = 0; 275 | var best_score = MIN_SCORE; 276 | if(flag) best_score = MAX_SCORE; 277 | 278 | for(var id = 0; id < steps.length; id++){ 279 | 280 | /***********************************\ 281 | * 更新节点值 282 | \***********************************/ 283 | move(board, steps[id]); 284 | // 285 | //console.log("step: " + steps[id].from.r + " " +steps[id].from.c + " " + steps[id].to.r + " " + steps[id].to.c) 286 | if(deep==1){ 287 | //console.log("end"); 288 | score = ai.evaluate(board, player_id); 289 | } 290 | else { 291 | score = ai.evaluate(board, player_id); 292 | if(Math.abs(score) < 9000){ 293 | result = ai.Search(ai.board, 1-player_id, deep-1, best_score); 294 | score = result.score; 295 | } 296 | } 297 | unmove(board, steps[id]); 298 | 299 | /***********************************\ 300 | * 更新最优走法 301 | \***********************************/ 302 | if( (!flag && score >= best_score) || (flag && score <= best_score)){ 303 | if(!(Math.abs(score - best_score) == 0 && Math.floor((Math.random() * 3)) == 0)){ 304 | best_id = id; 305 | best_score = score; 306 | } 307 | } 308 | 309 | /***********************************\ 310 | * a-b 剪子 311 | \***********************************/ 312 | if(flag && now_best > best_score) { 313 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 314 | //ai.set[b_str] = result; 315 | return result; 316 | } 317 | else if(!flag && now_best < best_score){ 318 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 319 | //ai.set[b_str] = result; 320 | return result; 321 | } 322 | } 323 | result = {score: best_score, step: best_id>=0?steps[best_id]:null}; 324 | //ai.set[b_str] = result; 325 | return result; 326 | } 327 | 328 | ai.evaluate = function(board, last_player_id){ 329 | 330 | score_table = { 331 | jiang: [ 332 | [0 ,0 ,0 ,9980,9999,9980,0 ,0 ,0 ], 333 | [0 ,0 ,0 ,9970,9970,9970,0 ,0 ,0 ], 334 | [0 ,0 ,0 ,9950,9950,9950,0 ,0 ,0 ], 335 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 336 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 337 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 338 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 339 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 340 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 341 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 342 | ], 343 | 344 | shi: [ 345 | [0 ,0 ,0 ,200 ,0 ,200 ,0 ,0 ,0 ], 346 | [0 ,0 ,0 ,0 ,240 ,0 ,0 ,0 ,0 ], 347 | [0 ,0 ,0 ,200 ,0 ,200 ,0 ,0 ,0 ], 348 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 349 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 350 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 351 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 352 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 353 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 354 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 355 | ], 356 | 357 | xiang: [ 358 | [0 ,0 ,210 ,0 ,0 ,0 ,210 ,0 ,0 ], 359 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 360 | [200 ,0 ,0 ,0 ,250 ,0 ,0 ,0 ,200 ], 361 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 362 | [0 ,0 ,200 ,0 ,0 ,0 ,200 ,0 ,0 ], 363 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 364 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 365 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 366 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 367 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 368 | ], 369 | 370 | zu: [ 371 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 372 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 373 | [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ], 374 | [150 ,0 ,150 ,0 ,230 ,0 ,150 ,0 ,150 ], 375 | [140 ,0 ,170 ,0 ,200 ,0 ,170 ,0 ,140 ], 376 | 377 | [180 ,190 ,200 ,200 ,210 ,200 ,200 ,190 ,180 ], 378 | [180 ,190 ,200 ,210 ,210 ,210 ,200 ,190 ,180 ], 379 | [190 ,190 ,200 ,220 ,220 ,220 ,210 ,190 ,190 ], 380 | [170 ,180 ,200 ,230 ,230 ,230 ,200 ,180 ,170 ], 381 | [160 ,160 ,190 ,200 ,200 ,200 ,190 ,160 ,160 ], 382 | ], 383 | 384 | ju: [ 385 | [1190,1240,1200,1200,1200,1200,1200,1240,1190], 386 | [1200,1220,1200,1210,1200,1210,1200,1220,1200], 387 | [1190,1220,1200,1200,1200,1200,1200,1220,1190], 388 | [1210,1220,1200,1200,1200,1200,1200,1220,1210], 389 | [1220,1250,1220,1260,1200,1260,1220,1250,1220], 390 | 391 | [1230,1240,1230,1240,1230,1240,1230,1240,1230], 392 | [1230,1230,1240,1230,1230,1230,1240,1230,1230], 393 | [1230,1230,1230,1230,1240,1230,1230,1230,1230], 394 | [1230,1240,1230,1230,1240,1230,1230,1240,1230], 395 | [1250,1250,1230,1250,1240,1250,1230,1250,1250], 396 | ], 397 | 398 | ma: [ 399 | [450 ,500 ,500 ,480 ,470 ,480 ,500 ,500 ,450 ], 400 | [450 ,510 ,510 ,470 ,480 ,470 ,510 ,510 ,450 ], 401 | [500 ,500 ,540 ,510 ,500 ,510 ,540 ,500 ,500 ], 402 | [500 ,520 ,520 ,510 ,500 ,510 ,520 ,520 ,500 ], 403 | [500 ,530 ,540 ,530 ,520 ,530 ,540 ,530 ,500 ], 404 | 405 | [530 ,540 ,540 ,540 ,540 ,530 ,540 ,540 ,530 ], 406 | [530 ,530 ,540 ,530 ,530 ,530 ,540 ,530 ,530 ], 407 | [530 ,530 ,540 ,550 ,530 ,550 ,540 ,530 ,530 ], 408 | [520 ,530 ,550 ,530 ,530 ,530 ,550 ,530 ,520 ], 409 | [510 ,530 ,540 ,530 ,530 ,530 ,540 ,530 ,510 ], 410 | ], 411 | 412 | pao: [ 413 | [500 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,500 ], 414 | [500 ,500 ,500 ,500 ,500 ,500 ,500 ,500 ,500 ], 415 | [510 ,500 ,510 ,520 ,540 ,520 ,510 ,500 ,510 ], 416 | [500 ,500 ,500 ,500 ,550 ,500 ,500 ,500 ,500 ], 417 | [500 ,500 ,500 ,500 ,550 ,500 ,500 ,500 ,500 ], 418 | 419 | [510 ,510 ,510 ,510 ,550 ,510 ,510 ,510 ,510 ], 420 | [510 ,510 ,510 ,500 ,550 ,500 ,510 ,510 ,510 ], 421 | [510 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,510 ], 422 | [510 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,510 ], 423 | [550 ,540 ,500 ,500 ,500 ,500 ,500 ,540 ,550 ], 424 | ] 425 | 426 | }; 427 | 428 | score = 0; 429 | Kpos = {r:-1,c:-1}; 430 | kpos = {r:-1,c:-1}; 431 | for(var r = 0; r<10;r++){ 432 | for(var c = 0; c<9;c++){ 433 | chess = board[r][c]; 434 | if(chess){ 435 | if(chess.type == "jiang"){ 436 | if(chess.player_id==0)Kpos = {r:r,c:c}; 437 | if(chess.player_id==1)kpos = {r:r,c:c}; 438 | } 439 | 440 | tr = (chess.player_id==0?r:9-r); 441 | //console.log(chess.player_id + " " + ai.myplayer_id); 442 | if(chess.player_id == ai.myplayer_id){ 443 | // console.log("tr: " + tr + " c: " + c + " score: " + score + " " + score_table[chess.type][tr][c]); 444 | score += score_table[chess.type][tr][c]*1.1; 445 | } 446 | else 447 | score -= score_table[chess.type][tr][c]*0.9; // 对方的子分值略低,防止AI不断对子 448 | } 449 | } 450 | } 451 | 452 | // 将帅见面,谁刚走谁输 453 | if(Math.abs(score)>9000) return score; 454 | if(Kpos.c > 0 && kpos.c > 0 && Kpos.c == kpos.c){ 455 | if(countChess(board, kpos, Kpos)==2 ){ 456 | if(last_player_id == ai.myplayer_id){ 457 | score = MIN_SCORE; 458 | } 459 | else score = MAX_SCORE; 460 | } 461 | } 462 | return score; 463 | } 464 | 465 | return ai; 466 | } 467 | } 468 | 469 | -------------------------------------------------------------------------------- /static/js/crafty/crafty-min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * craftyjs 0.7.1 3 | * http://craftyjs.com/ 4 | * 5 | * Copyright 2016, Louis Stowasser 6 | * Dual licensed under the MIT or GPL licenses. 7 | */ 8 | 9 | !function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g1)for(var c=1;c0&&(this.vx+=this._directionSpeed[a].x,this.vy+=this._directionSpeed[a].y)},__unapplyActiveDirections:function(){for(var a in this._activeDirections)this._activeDirections[a]>0&&(this.vx-=this._directionSpeed[a].x,this.vy-=this._directionSpeed[a].y)},enableControl:function(){return this.disableControls&&this.__applyActiveDirections(),this.disableControls=!1,this},disableControl:function(){return this.disableControls||this.__unapplyActiveDirections(),this.disableControls=!0,this}}),d.c("Jumper",{_jumpSpeed:300,canJump:!0,init:function(){this.requires("Supportable, Motion, Keyboard"),this.enableControl=this.enableControl||function(){this.disableControls=!1},this.disableControl=this.disableControl||function(){this.disableControls=!0}},remove:function(){this.unbind("KeyDown",this._keydown_jumper)},_keydown_jumper:function(a){if(!this.disableControls&&this._jumpKeys[a.key]){var b=this.ground;this.canJump=!!b,this.trigger("CheckJumping",b),this.canJump&&(this.vy=-this._jumpSpeed)}},jumper:function(a,b){b?this._jumpSpeed=a:b=a,this._jumpKeys={};for(var c=0;c0?1:-1,e={acceleration:b,rawAcceleration:"["+Math.round(b.x)+", "+Math.round(b.y)+", "+Math.round(b.z)+"]",facingUp:c,tiltLR:Math.round(b.x/9.81*-90),tiltFB:Math.round((b.y+9.81)/9.81*90*c)};d.device._deviceMotionCallback(e)},deviceOrientation:function(a){this._deviceOrientationCallback=a,d.support.deviceorientation&&(window.DeviceOrientationEvent?d.addEvent(this,window,"deviceorientation",this._normalizeDeviceOrientation):window.OrientationEvent&&d.addEvent(this,window,"MozOrientation",this._normalizeDeviceOrientation))},deviceMotion:function(a){this._deviceMotionCallback=a,d.support.devicemotion&&window.DeviceMotionEvent&&d.addEvent(this,window,"devicemotion",this._normalizeDeviceMotion)}}})},{"../core/core.js":7}],4:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.extend({over:null,mouseObjs:0,mousePos:{},lastEvent:null,touchObjs:0,selected:!1,keydown:{},detectBlur:function(a){var b=a.clientX>d.stage.x&&a.clientXd.stage.y&&a.clientYc;c++){var f,g,h,i=!1,j=d.domHelper.translate(b[c].clientX,b[c].clientY),k=a.target?a.target:a.srcElement;b[c].realX=f=j.x,b[c].realY=g=j.y,h=this.findClosestTouchEntity(f,g,k),h&&(h.trigger("TouchStart",b[c]),i=this.fingerDownIndexByEntity(h));var l=this.setTouch(b[c],h);i!==!1&&i>=0?this.fingers[i]=l:this.fingers.push(l)}},handleMove:function(a){for(var b=a.changedTouches,c=0,e=b.length;e>c;c++){var f,g,h,i=this.fingerDownIndexById(b[c].identifier),j=d.domHelper.translate(b[c].clientX,b[c].clientY),k=a.target?a.target:a.srcElement;b[c].realX=f=j.x,b[c].realY=g=j.y,h=this.findClosestTouchEntity(f,g,k),i>=0&&("undefined"!=typeof this.fingers[i].entity&&(this.fingers[i].entity==h?this.fingers[i].entity.trigger("TouchMove",b[c]):("object"==typeof h&&h.trigger("TouchStart",b[c]),this.fingers[i].entity.trigger("TouchEnd"))),this.fingers[i].entity=h,this.fingers[i].realX=f,this.fingers[i].realY=g)}},handleEnd:function(a){for(var b=a.changedTouches,c="touchcancel"==a.type?"TouchCancel":"TouchEnd",d=0,e=b.length;e>d;d++){var f=this.fingerDownIndexById(b[d].identifier);f>=0&&(this.fingers[f].entity&&this.fingers[f].entity.trigger(c),this.fingers.splice(f,1))}},setTouch:function(a,b){return{identifier:a.identifier,realX:a.realX,realY:a.realY,entity:b}},findClosestTouchEntity:function(a,b,c){return d.findClosestEntityByComponent("Touch",a,b,c)},fingerDownIndexById:function(a){for(var b=0,c=this.fingers.length;c>b;b++){var d=this.fingers[b].identifier;if(d==a)return b}return-1},fingerDownIndexByEntity:function(a){for(var b=0,c=this.fingers.length;c>b;b++){var d=this.fingers[b].entity;if(d==a)return b}return-1},mimicMouse:function(a){var b,c=d.lastEvent;"touchstart"===a.type?b="mousedown":"touchmove"===a.type?b="mousemove":"touchend"===a.type?b="mouseup":"touchcancel"===a.type?b="mouseup":"touchleave"===a.type&&(b="mouseup"),a.touches&&a.touches.length?first=a.touches[0]:a.changedTouches&&a.changedTouches.length&&(first=a.changedTouches[0]);var f=e.createEvent("MouseEvent");f.initMouseEvent(b,!0,!0,window,1,first.screenX,first.screenY,first.clientX,first.clientY,!1,!1,!1,!1,0,a.relatedTarget),first.target.dispatchEvent(f),null!==c&&"mousedown"==c.type&&"mouseup"==b&&(b="click",f=e.createEvent("MouseEvent"),f.initMouseEvent(b,!0,!0,window,1,first.screenX,first.screenY,first.clientX,first.clientY,!1,!1,!1,!1,0,a.relatedTarget),first.target.dispatchEvent(f))}},findClosestEntityByComponent:function(a,b,c,e){var f,g,h,i=e?e:d.stage.elem,j=0,k=-1,l={};if("CANVAS"!=i.nodeName){for(;"string"!=typeof i.id&&-1==i.id.indexOf("ent");)i=i.parentNode;var m=d(parseInt(i.id.replace("ent",""),10));m.__c[a]&&m.isAt(b,c)&&(f=m)}if(!f)for(g=d.map.search({_x:b,_y:c,_w:1,_h:1},!1),h=g.length;h>j;++j)if(g[j].__c[a]&&g[j]._visible){var n=g[j],o=!1;if(!l[n[0]]&&(l[n[0]]=!0,n.mapArea?n.mapArea.containsPoint(b,c)&&(o=!0):n.isAt(b,c)&&(o=!0),o&&(n._z>=k||-1===k))){if(n._z===k&&n[0]0?1:-1,d.trigger("MouseWheelScroll",a)},keyboardDispatch:function(a){for(var b=a,c={},e="char charCode keyCode type shiftKey ctrlKey metaKey timestamp".split(" "),f=e.length;f;){var g=e[--f];c[g]=b[g]}return c.which=null!==b.charCode?b.charCode:b.keyCode,c.key=b.keyCode||b.which,c.originalEvent=b,a=c,"keydown"===a.type?d.keydown[a.key]!==!0&&(d.keydown[a.key]=!0,d.trigger("KeyDown",a)):"keyup"===a.type&&(delete d.keydown[a.key],d.trigger("KeyUp",a)),d.selected&&!(8==a.key||a.key>=112&&a.key<=135)?(b.stopPropagation?b.stopPropagation():b.cancelBubble=!0,b.target&&"INPUT"!==b.target.nodeName&&"TEXTAREA"!==b.target.nodeName&&(b.preventDefault?b.preventDefault():b.returnValue=!1),!1):void 0}}),d._preBind("Load",function(){d.addEvent(this,"keydown",d.keyboardDispatch),d.addEvent(this,"keyup",d.keyboardDispatch),d.addEvent(this,d.stage.elem,"mousedown",d.mouseDispatch),d.addEvent(this,d.stage.elem,"mouseup",d.mouseDispatch),d.addEvent(this,e.body,"mouseup",d.detectBlur),d.addEvent(this,window,"blur",d.resetKeyDown),d.addEvent(this,d.stage.elem,"mousemove",d.mouseDispatch),d.addEvent(this,d.stage.elem,"click",d.mouseDispatch),d.addEvent(this,d.stage.elem,"dblclick",d.mouseDispatch),d.addEvent(this,d.stage.elem,"touchstart",d.touchDispatch),d.addEvent(this,d.stage.elem,"touchmove",d.touchDispatch),d.addEvent(this,d.stage.elem,"touchend",d.touchDispatch),d.addEvent(this,d.stage.elem,"touchcancel",d.touchDispatch),d.addEvent(this,d.stage.elem,"touchleave",d.touchDispatch),"Moz"===d.support.prefix?d.addEvent(this,d.stage.elem,"DOMMouseScroll",d.mouseWheelDispatch):d.addEvent(this,d.stage.elem,"mousewheel",d.mouseWheelDispatch)}),d._preBind("CraftyStop",function(){d.removeEvent(this,"keydown",d.keyboardDispatch),d.removeEvent(this,"keyup",d.keyboardDispatch),d.stage&&(d.removeEvent(this,d.stage.elem,"mousedown",d.mouseDispatch),d.removeEvent(this,d.stage.elem,"mouseup",d.mouseDispatch),d.removeEvent(this,d.stage.elem,"mousemove",d.mouseDispatch),d.removeEvent(this,d.stage.elem,"click",d.mouseDispatch),d.removeEvent(this,d.stage.elem,"dblclick",d.mouseDispatch),d.removeEvent(this,d.stage.elem,"touchstart",d.touchDispatch),d.removeEvent(this,d.stage.elem,"touchmove",d.touchDispatch),d.removeEvent(this,d.stage.elem,"touchend",d.touchDispatch),d.removeEvent(this,d.stage.elem,"touchcancel",d.touchDispatch),d.removeEvent(this,d.stage.elem,"touchleave",d.touchDispatch),"Moz"===d.support.prefix?d.removeEvent(this,d.stage.elem,"DOMMouseScroll",d.mouseWheelDispatch):d.removeEvent(this,d.stage.elem,"mousewheel",d.mouseWheelDispatch)),d.removeEvent(this,e.body,"mouseup",d.detectBlur),d.removeEvent(this,window,"blur",d.resetKeyDown)}),d.c("Mouse",{init:function(){d.mouseObjs++,this.requires("AreaMap").bind("Remove",function(){d.mouseObjs--})}}),d.c("Touch",{init:function(){d.touchObjs++,this.requires("AreaMap").bind("Remove",function(){d.touchObjs--})}}),d.c("AreaMap",{init:function(){},areaMap:function(a){if(arguments.length>1){var b=Array.prototype.slice.call(arguments,0);a=new d.polygon(b)}else a=a.constructor===Array?new d.polygon(a.slice()):a.clone();return a.shift(this._x,this._y),this.mapArea=a,this.attach(this.mapArea),this.trigger("NewAreaMap",a),this}}),d.c("Button",{init:function(){var a=!d.mobile||d.mobile&&!d.multitouch()?"Mouse":"Touch";this.requires(a)}}),d.c("MouseDrag",{_dragging:!1,init:function(){this.requires("Mouse"),this.bind("MouseDown",this._ondown)},remove:function(){this.unbind("MouseDown",this._ondown)},_ondown:function(a){a.mouseButton===d.mouseButtons.LEFT&&this.startDrag(a)},_ondrag:function(a){return this._dragging&&0!==a.realX&&0!==a.realY?void this.trigger("Dragging",a):!1},_onup:function(a){a.mouseButton===d.mouseButtons.LEFT&&this.stopDrag(a)},startDrag:function(a){return this._dragging?void 0:(this._dragging=!0,d.addEvent(this,d.stage.elem,"mousemove",this._ondrag),d.addEvent(this,d.stage.elem,"mouseup",this._onup),this.trigger("StartDrag",a||d.lastEvent),this)},stopDrag:function(a){return this._dragging?(this._dragging=!1,d.removeEvent(this,d.stage.elem,"mousemove",this._ondrag),d.removeEvent(this,d.stage.elem,"mouseup",this._onup),this.trigger("StopDrag",a||d.lastEvent),this):void 0}}),d.c("Keyboard",{isDown:function(a){return"string"==typeof a&&(a=d.keys[a]),!!d.keydown[a]}})},{"../core/core.js":7}],5:[function(a,b,c){var d=a("../core/core.js");d.extend({keys:{BACKSPACE:8,TAB:9,ENTER:13,PAUSE:19,CAPS:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,INSERT:45,DELETE:46,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,MULTIPLY:106,ADD:107,SUBSTRACT:109,DECIMAL:110,DIVIDE:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,SHIFT:16,CTRL:17,ALT:18,PLUS:187,COMMA:188,MINUS:189,PERIOD:190,PULT_UP:29460,PULT_DOWN:29461,PULT_LEFT:4,PULT_RIGHT:5},mouseButtons:{LEFT:0,MIDDLE:1,RIGHT:2}})},{"../core/core.js":7}],6:[function(a,b,c){var d=function(a,b){this.timePerFrame=1e3/Crafty.timer.FPS(),this.duration=a,"function"==typeof b?this.easing_function=b:"string"==typeof b&&this.standardEasingFunctions[b]?this.easing_function=this.standardEasingFunctions[b]:this.easing_function=this.standardEasingFunctions.linear,this.reset()};d.prototype={duration:0,clock:0,steps:null,complete:!1,paused:!1,reset:function(){this.loops=1,this.clock=0,this.complete=!1,this.paused=!1},repeat:function(a){this.loops=a},setProgress:function(a,b){this.clock=this.duration*a,"undefined"!=typeof b&&(this.loops=b)},pause:function(){this.paused=!0},resume:function(){this.paused=!1,this.complete=!1},tick:function(a){if(!this.paused&&!this.complete)for(this.clock+=a,this.frames=Math.floor(this.clock/this.timePerFrame);this.clock>=this.duration&&this.complete===!1;)this.loops--,this.loops>0?this.clock-=this.duration:this.complete=!0},time:function(){return Math.min(this.clock/this.duration,1)},value:function(){return this.easing_function(this.time())},standardEasingFunctions:{linear:function(a){return a},smoothStep:function(a){return(3-2*a)*a*a},smootherStep:function(a){return(6*a*a-15*a+10)*a*a*a},easeInQuad:function(a){return a*a},easeOutQuad:function(a){return a*(2-a)},easeInOutQuad:function(a){return.5>a?2*a*a:(4-2*a)*a-1}}},b.exports=d},{}],7:[function(a,b,c){function d(){var a=f++;return a in i?d():a}function e(a){if(null===a||"object"!=typeof a)return a;var b=a.constructor();for(var c in a)b[c]=e(a[c]);return b}var f,g,h,i,j,k,l,m,n,o=a("./version"),p=function(a){return new p.fn.init(a)};h={},l=Array.prototype.slice,m=/\s*,\s*/,n=/\s+/;var q=function(){f=1,g=0,i={},j={},k=[]};q(),p.fn=p.prototype={init:function(a){if("string"!=typeof a)return a||(a=0,a in i||(i[a]=this)),a in i?(this[0]=a,this.length=1,this.__c||(this.__c={}),this._callbacks||p._addCallbackMethods(this),i[a]||(i[a]=this),i[a]):(this.length=0,this);var b,c,d,e,f,g,j,k=0,l=!1,o=!1;if("*"===a){g=0;for(b in i)this[g]=+b,g++;return this.length=g,1===g?i[this[0]]:this}-1!==a.indexOf(",")?(o=!0,d=m):-1!==a.indexOf(" ")&&(l=!0,d=n);for(b in i)if(i.hasOwnProperty(b))if(c=i[b],l||o){for(e=a.split(d),g=0,j=e.length,f=0;j>g;g++)c.__c[e[g]]&&f++;(l&&f===j||o&&f>0)&&(this[k++]=+b)}else c.__c[a]&&(this[k++]=+b);if(k>0&&!l&&!o&&this.extend(h[a]),e&&l)for(g=0;j>g;g++)this.extend(h[e[g]]);return this.length=k,1===k?i[this[k-1]]:(p._addCallbackMethods(this),this)},setName:function(a){var b=String(a);return this._entityName=b,this.trigger("NewEntityName",b),this},addComponent:function(a){var b,c,d=0;for(b=1===arguments.length&&-1!==a.indexOf(",")?a.split(m):arguments;d1)for(b=arguments.length;b>d;d++)this.has(arguments[d])?this.removeComponent(arguments[d]):this.addComponent(arguments[d]);else if(-1!==a.indexOf(","))for(c=a.split(m),b=c.length;b>d;d++)this.has(c[d])?this.removeComponent(c[d]):this.addComponent(c[d]);else this.has(a)?this.removeComponent(a):this.addComponent(a);return this},requires:function(a){return this.addComponent(a)},removeComponent:function(a,b){var c=h[a];if(this.trigger("RemoveComponent",a),c&&"events"in c){var d=c.events;for(var e in d){var f="function"==typeof d[e]?d[e]:c[d[e]];this.unbind(e,f)}}if(c&&"remove"in c&&c.remove.call(this,!1),b===!1&&c)for(var g in c)delete this[g];return delete this.__c[a],this},getId:function(){return this[0]},has:function(a){return!!this.__c[a]},attr:function(a,b,c,d){return 1===arguments.length&&"string"==typeof arguments[0]?this._attr_get(a):this._attr_set(a,b,c,d)},_attr_get:function(a,b){var c,d,e;return("undefined"==typeof b||null===b)&&(b=this),a.indexOf(".")>-1?(d=a.split("."),c=d.shift(),e=d.join("."),this._attr_get(d.join("."),b[c])):b[a]},_attr_set:function(){var a,b,c;return"string"==typeof arguments[0]?(a=this._set_create_object(arguments[0],arguments[1]),b=!!arguments[2],c=arguments[3]||arguments[0].indexOf(".")>-1):(a=arguments[0],b=!!arguments[1],c=!!arguments[2]),b||this.trigger("Change",a),c?this._recursive_extend(a,this):this.extend.call(this,a),this},_set_create_object:function(a,b){var c,d,e,f={};return a.indexOf(".")>-1?(c=a.split("."),d=c.shift(),e=c.join("."),f[d]=this._set_create_object(e,b)):f[a]=b,f},_recursive_extend:function(a,b){var c;for(c in a)a[c].constructor===Object?b[c]=this._recursive_extend(a[c],b[c]):b[c]=a[c];return b},toArray:function(){return l.call(this,0)},timeout:function(a,b){return this.each(function(){var c=this;setTimeout(function(){a.call(c)},b)}),this},bind:function(a,b){if(1===this.length)this._bindCallback(a,b);else for(var c=0;cb;b++)i[this[b]]&&a.call(i[this[b]],b);return this},get:function(a){var b=this.length;if("undefined"!=typeof a){if(a>=b||0>a+b)return;return a>=0?i[this[a]]:i[this[a+b]]}for(var c=0,d=[];b>c;c++)i[this[c]]&&d.push(i[this[c]]);return d},clone:function(){var a,b,c=this.__c,d=p.e();for(a in c)d.addComponent(a);for(b in this)"0"!=b&&"_global"!=b&&"_changed"!=b&&"function"!=typeof this[b]&&"object"!=typeof this[b]&&(d[b]=this[b]);return d},setter:function(a,b){return this.defineField(a,function(){},b)},defineField:function(a,b,c){return p.defineField(this,a,b,c),this},destroy:function(){this.each(function(){var a;this.trigger("Remove");for(var b in this.__c)a=h[b],a&&"remove"in a&&a.remove.call(this,!0);this._unbindAll(),delete i[this[0]]})}},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(a){var b,c=this;if(!a)return c;for(b in a)c!==a[b]&&(c[b]=a[b]);return c},p._callbackMethods={_bindCallback:function(a,b){var c=this._callbacks[a];c||(c=this._callbacks[a]=(j[a]||(j[a]={}))[this[0]]=[],c.context=this,c.depth=0),c.push(b)},_runCallbacks:function(a,b){if(this._callbacks[a]){var c,d=this._callbacks[a],e=d.length;for(d.depth++,c=0;e>c;c++)"undefined"==typeof d[c]?d.depth<=1&&(d.splice(c,1),c--,e--,0===d.length&&(delete this._callbacks[a],delete j[a][this[0]])):d[c].call(this,b);d.depth--}},_unbindCallbacks:function(a,b){if(this._callbacks[a])for(var c=this._callbacks[a],d=0;d0&&p.trigger("MeasureWaitTime",currentTime-h),c+i>=currentTime)return void(h=currentTime);var m=currentTime-(c+i);m>20*k&&(i+=m-k,m=k),"fixed"===d?(l=Math.ceil(m/k),l=Math.min(l,e),b=k):"variable"===d?(l=1,b=m,b=Math.min(b,f)):"semifixed"===d&&(l=Math.ceil(m/f),b=m/l);for(var n=0;l>n;n++){j=currentTime;var o={frame:g++,dt:b,gameTime:c};p.trigger("EnterFrame",o),p.trigger("ExitFrame",o),c+=b,currentTime=(new Date).getTime(),p.trigger("MeasureFrameTime",currentTime-j)}l>0&&(a=currentTime,p.trigger("PreRender"),p.trigger("RenderScene"),p.trigger("PostRender"),currentTime=(new Date).getTime(),p.trigger("MeasureRenderTime",currentTime-a)),h=currentTime},FPS:function(a){return"undefined"==typeof a?j:(j=a,k=1e3/j,p.trigger("FPSChange",a),void 0)},simulateFrames:function(a,b){for("undefined"==typeof b&&(b=k);a-- >0;){var c={frame:g++,dt:b};p.trigger("EnterFrame",c),p.trigger("ExitFrame",c)}p.trigger("PreRender"),p.trigger("RenderScene"),p.trigger("PostRender")}}}(),e:function(){var a=d();return i[a]=null,i[a]=p(a),arguments.length>0&&i[a].addComponent.apply(i[a],arguments),i[a].setName("Entity #"+a),i[a].addComponent("obj"),p.trigger("NewEntity",{id:a}),i[a]},c:function(a,b){h[a]=b},trigger:function(a,b){var c,d,e=j[a]||(j[a]={});for(c in e)e.hasOwnProperty(c)&&(d=e[c],d&&0!==d.length&&d.context._runCallbacks(a,b))},bind:function(a,b){return this._bindCallback(a,b),b},uniqueBind:function(a,b){return this.unbind(a,b),this.bind(a,b)},one:function(a,b){var c=this,d=function(e){b.call(c,e),c.unbind(a,d)};return c.bind(a,d)},unbind:function(a,b){this._unbindCallbacks(a,b)},frame:function(){return g},components:function(){return h},isComp:function(a){return a in h},debug:function(a){return"handlers"===a?j:i},settings:function(){var a={},b={};return{register:function(a,c){b[a]=c},modify:function(c,d){b[c]&&(b[c].call(a[c],d),a[c]=d)},get:function(b){return a[b]}}}(),defineField:function(a,b,c,d){Object.defineProperty(a,b,{get:c,set:d,configurable:!1,enumerable:!0})},clone:e}),"function"==typeof define&&define("crafty",[],function(){return p}),b.exports=p},{"./version":16}],8:[function(a,b,c){(function(c){var d=a("./core"),e="undefined"!=typeof window&&window.document;!function(){var a=d.support={},b="undefined"!=typeof navigator&&navigator.userAgent.toLowerCase()||"undefined"!=typeof c&&c.version,f=/(webkit)[ \/]([\w.]+)/.exec(b)||/(o)pera(?:.*version)?[ \/]([\w.]+)/.exec(b)||/(ms)ie ([\w.]+)/.exec(b)||/(moz)illa(?:.*? rv:([\w.]+))?/.exec(b)||/(v)\d+\.(\d+)/.exec(b)||[],g=/iPad|iPod|iPhone|Android|webOS|IEMobile/i.exec(b);if(g&&(d.mobile=g[0]),a.defineProperty=function(){if(!("defineProperty"in Object))return!1;try{Object.defineProperty({},"x",{})}catch(a){return!1}return!0}(),a.audio="undefined"!=typeof window&&"canPlayType"in e.createElement("audio"),a.prefix=f[1]||f[0],"moz"===a.prefix&&(a.prefix="Moz"),"o"===a.prefix&&(a.prefix="O"),"v"===a.prefix&&(a.prefix="node"),f[2]&&(a.versionName=f[2],a.version=+f[2].split(".")[0]),a.canvas="undefined"!=typeof window&&"getContext"in e.createElement("canvas"),a.canvas){var h;try{var i=e.createElement("canvas");h=i.getContext("webgl")||i.getContext("experimental-webgl"),h.viewportWidth=a.canvas.width,h.viewportHeight=a.canvas.height}catch(j){}a.webgl=!!h}else a.webgl=!1;a.css3dtransform="undefined"!=typeof window&&("undefined"!=typeof e.createElement("div").style.Perspective||"undefined"!=typeof e.createElement("div").style[a.prefix+"Perspective"]),a.deviceorientation="undefined"!=typeof window&&("undefined"!=typeof window.DeviceOrientationEvent||"undefined"!=typeof window.OrientationEvent),a.devicemotion="undefined"!=typeof window&&"undefined"!=typeof window.DeviceMotionEvent}(),b.exports={_events:{},addEvent:function(a,b,c,d){3===arguments.length&&(d=c,c=b,b=window.document);var e=function(b){d.call(a,b)},f=a[0]||"";this._events[f+b+c+d]||(this._events[f+b+c+d]=e,b.addEventListener(c,e,!1))},removeEvent:function(a,b,c,d){3===arguments.length&&(d=c,c=b,b=window.document);var e=a[0]||"",f=this._events[e+b+c+d];f&&(b.removeEventListener(c,f,!1),delete this._events[e+b+c+d])},background:function(a){d.stage.elem.style.background=a}}}).call(this,a("_process"))},{"./core":7,_process:1}],9:[function(a,b,c){var d=a("../core/core.js");b.exports={assets:{},__paths:{audio:"",images:""},paths:function(a){return"undefined"==typeof a?this.__paths:(a.audio&&(this.__paths.audio=a.audio),void(a.images&&(this.__paths.images=a.images)))},asset:function(a,b){return 1===arguments.length?d.assets[a]:d.assets[a]?void 0:(d.assets[a]=b,this.trigger("NewAsset",{key:a,value:b}),b)},image_whitelist:["jpg","jpeg","gif","png","svg"],load:function(a,b,c,e){function f(){var a=this.src;this.removeEventListener&&this.removeEventListener("canplaythrough",f,!1),m++,c&&c({loaded:m,total:n,percent:m/n*100,src:a}),m===n&&b&&b()}function g(){var a=this.src;e&&e({loaded:m,total:n,percent:m/n*100,src:a}),m++,m===n&&b&&b()}Array.isArray(a)&&d.log("Calling Crafty.load with an array of assets no longer works; see the docs for more details."),a="string"==typeof a?JSON.parse(a):a;var h,i,j,k,l,m=0,n=(a.audio?Object.keys(a.audio).length:0)+(a.images?Object.keys(a.images).length:0)+(a.sprites?Object.keys(a.sprites).length:0),o=d.support.audio,p=d.paths(),q=function(a){ 10 | return a.substr(a.lastIndexOf(".")+1).toLowerCase()},r=function(a,b){return-1===b.search("://")?"audio"==a?p.audio+b:p.images+b:b},s=function(a){return d.asset(a)||null},t=function(a){return d.audio.supports(q(a))},u=function(a){return-1!=d.image_whitelist.indexOf(q(a))},v=function(a,b){a.onload=f,"webkit"===d.support.prefix&&(a.src=""),a.src=b};for(k in a)for(l in a[k])if(a[k].hasOwnProperty(l)){if(h=a[k][l],"audio"===k&&o){if("object"==typeof h){var w=[];for(var x in h)i=r(k,h[x]),!s(i)&&t(h[x])&&w.push(i);j=d.audio.add(l,w).obj}else"string"==typeof h&&t(h)&&(i=r(k,h),s(i)||(j=d.audio.add(l,i).obj));j&&j.addEventListener&&j.addEventListener("canplaythrough",f,!1)}else l="sprites"===k?l:h,i=r(k,l),u(l)&&(j=s(i),j||(j=new Image,"sprites"===k&&d.sprite(h.tile,h.tileh,i,h.map,h.paddingX,h.paddingY,h.paddingAroundBorder),d.asset(i,j)),v(j,i));j?j.onerror=g:--n}0===n&&b()},removeAssets:function(a){a="string"==typeof a?JSON.parse(a):a;var b,c,e,f,g=d.paths(),h=function(a,b){return-1===b.search("://")?"audio"==a?g.audio+b:g.images+b:b};for(e in a)for(f in a[e])if(a[e].hasOwnProperty(f))if(b=a[e][f],"audio"===e)if("object"==typeof b)for(var i in b)c=h(e,b[i]),d.asset(c)&&d.audio.remove(f);else"string"==typeof b&&(c=h(e,b),d.asset(c)&&d.audio.remove(f));else if(f="sprites"===e?f:b,c=h(e,f),d.asset(c)){if("sprites"===e)for(var j in b.map)delete d.components()[j];delete d.assets[c]}}}},{"../core/core.js":7}],10:[function(a,b,c){b.exports={init:function(){this.changed=[],this.bind("Change",this._changed_attributes),this.bind("Change",this._changed_triggers)},_changed_triggers:function(a,b){var c;b=Crafty.extend.call({pre:""},b);for(c in a)this.trigger("Change["+b.pre+c+"]",a[c]),a[c].constructor===Object&&this._changed_triggers(a[c],{pre:b.pre+c+"."})},_changed_attributes:function(a){var b;for(b in a)this.changed.push(b);return this},is_dirty:function(a){return 0===arguments.length?!!this.changed.length:this.changed.indexOf(a)>-1}}},{}],11:[function(a,b,c){var d=a("../core/core.js");b.exports={_scenes:{},_current:null,scene:function(a,b,c){return 1===arguments.length||"function"!=typeof arguments[1]?void d.enterScene(a,arguments[1]):void d.defineScene(a,b,c)},defineScene:function(a,b,c){if("function"!=typeof b)throw"Init function is the wrong type.";this._scenes[a]={},this._scenes[a].initialize=b,"undefined"!=typeof c&&(this._scenes[a].uninitialize=c)},enterScene:function(a,b){if("function"==typeof b)throw"Scene data cannot be a function";d.trigger("SceneDestroy",{newScene:a}),d.viewport.reset(),d("2D").each(function(){this.has("Persist")||this.destroy()}),null!==this._current&&"uninitialize"in this._scenes[this._current]&&this._scenes[this._current].uninitialize.call(this);var c=this._current;this._current=a,d.trigger("SceneChange",{oldScene:c,newScene:a}),this._scenes.hasOwnProperty(a)?this._scenes[a].initialize.call(this,b):d.error('The scene "'+a+'" does not exist')}}},{"../core/core.js":7}],12:[function(a,b,c){var d=a("../core/core.js");try{var e="undefined"!=typeof window&&window.localStorage||new a("node-localstorage").LocalStorage("./localStorage")}catch(f){var e=null}var g=function(a,b){var c=b;if(!e)return d.error("Local storage is not accessible. (Perhaps you are including crafty.js cross-domain?)"),!1;if(1===arguments.length)try{return JSON.parse(e.getItem(a))}catch(f){return e.getItem(a)}else"object"==typeof b&&(c=JSON.stringify(b)),e.setItem(a,c)};g.remove=function(a){return e?void e.removeItem(a):void d.error("Local storage is not accessible. (Perhaps you are including crafty.js cross-domain?)")},b.exports=g},{"../core/core.js":7}],13:[function(a,b,c){var d=a("../core/core.js");d._systems={},d.s=function(a,b,c){return b?void(c===!1?(d._systems[a]=new d.CraftySystem(a,b),d.trigger("SystemLoaded",a)):d._registerLazySystem(a,b)):d._systems[a]},d._registerLazySystem=function(a,b){Object.defineProperty(d._systems,a,{get:function(){return Object.defineProperty(d._systems,a,{value:new d.CraftySystem(a,b),writable:!0,enumerable:!0,configurable:!0}),d.trigger("SystemLoaded",a),d._systems[a]},configurable:!0})},d.CraftySystem=function(){return systemID=1,function(a,b){if(this.name=a,!b)return this;if(this._systemTemplate=b,this.extend(b),d._addCallbackMethods(this),this[0]="system"+systemID++,"function"==typeof this.init&&this.init(a),"events"in b){var c=b.events;for(var e in c){var f="function"==typeof c[e]?c[e]:b[c[e]];this.bind(e,f)}}}}(),d.CraftySystem.prototype={extend:function(a){for(var b in a)"undefined"==typeof this[b]&&(this[b]=a[b])},bind:function(a,b){return this._bindCallback(a,b),this},trigger:function(a,b){return this._runCallbacks(a,b),this},unbind:function(a,b){return this._unbindCallbacks(a,b),this},one:function(a,b){var c=this,d=function(e){b.call(c,e),c.unbind(a,d)};return c.bind(a,d)},uniqueBind:function(a,b){return this.unbind(a,b),this.bind(a,b)},destroy:function(){d.trigger("SystemDestroyed",this),"function"==typeof this.remove&&this.remove(),this._unbindAll(),delete d._systems[this.name]}}},{"../core/core.js":7}],14:[function(a,b,c){b.exports={init:function(){this._delays=[],this.bind("EnterFrame",function(a){for(var b=this._delays.length;--b>=0;){var c=this._delays[b];if(c===!1)this._delays.splice(b,1);else{for(c.accumulator+=a.dt;c.accumulator>=c.delay&&c.repeat>=0;)c.accumulator-=c.delay,c.repeat--,c.callback.call(this);c.repeat<0&&(this._delays.splice(b,1),"function"==typeof c.callbackOff&&c.callbackOff.call(this))}}})},delay:function(a,b,c,d){return this._delays.push({accumulator:0,callback:a,callbackOff:d,delay:b,repeat:(0>c?1/0:c)||0}),this},cancelDelay:function(a){for(var b=this._delays.length;--b>=0;){var c=this._delays[b];c&&c.callback==a&&(this._delays[b]=!1)}return this}}},{}],15:[function(a,b,c){b.exports={init:function(){this.tweenGroup={},this.tweenStart={},this.tweens=[],this.uniqueBind("EnterFrame",this._tweenTick)},_tweenTick:function(a){var b,c,d;for(d=this.tweens.length-1;d>=0;d--)b=this.tweens[d],b.easing.tick(a.dt),c=b.easing.value(),this._doTween(b.props,c),b.easing.complete&&(this.tweens.splice(d,1),this._endTween(b.props))},_doTween:function(a,b){for(var c in a)this[c]=(1-b)*this.tweenStart[c]+b*a[c]},tween:function(a,b,c){var d={props:a,easing:new Crafty.easing(b,c)};for(var e in a)"undefined"!=typeof this.tweenGroup[e]&&this.cancelTween(e),this.tweenStart[e]=this[e],this.tweenGroup[e]=a;return this.tweens.push(d),this},cancelTween:function(a){if("string"==typeof a)"object"==typeof this.tweenGroup[a]&&delete this.tweenGroup[a][a];else if("object"==typeof a)for(var b in a)this.cancelTween(b);return this},pauseTweens:function(){this.tweens.map(function(a){a.easing.pause()})},resumeTweens:function(){this.tweens.map(function(a){a.easing.resume()})},_endTween:function(a){for(var b in a)delete this.tweenGroup[b];this.trigger("TweenEnd",a)}}},{}],16:[function(a,b,c){b.exports="0.7.1"},{}],17:[function(a,b,c){var d=a("./core/core");d.easing=a("./core/animation"),d.extend(a("./core/extensions")),d.extend(a("./core/loader")),d.c("Model",a("./core/model")),d.extend(a("./core/scenes")),d.storage=a("./core/storage"),d.c("Delay",a("./core/time")),d.c("Tween",a("./core/tween")),a("./core/systems"),a("./spatial/2d"),a("./spatial/collision"),a("./spatial/spatial-grid"),a("./spatial/rect-manager"),a("./spatial/math"),a("./graphics/canvas"),a("./graphics/canvas-layer"),a("./graphics/color"),a("./graphics/dom"),a("./graphics/dom-helper"),a("./graphics/dom-layer"),a("./graphics/drawing"),a("./graphics/gl-textures"),a("./graphics/html"),a("./graphics/image"),a("./graphics/particles"),a("./graphics/sprite-animation"),a("./graphics/sprite"),a("./graphics/text"),a("./graphics/viewport"),a("./graphics/webgl"),a("./isometric/diamond-iso"),a("./isometric/isometric"),a("./controls/inputs"),a("./controls/controls"),a("./controls/device"),a("./controls/keycodes"),a("./sound/sound"),a("./debug/debug-layer"),a("./debug/logging"),window&&(window.Crafty=d),b.exports=d},{"./controls/controls":2,"./controls/device":3,"./controls/inputs":4,"./controls/keycodes":5,"./core/animation":6,"./core/core":7,"./core/extensions":8,"./core/loader":9,"./core/model":10,"./core/scenes":11,"./core/storage":12,"./core/systems":13,"./core/time":14,"./core/tween":15,"./debug/debug-layer":18,"./debug/logging":19,"./graphics/canvas":21,"./graphics/canvas-layer":20,"./graphics/color":22,"./graphics/dom":25,"./graphics/dom-helper":23,"./graphics/dom-layer":24,"./graphics/drawing":26,"./graphics/gl-textures":27,"./graphics/html":28,"./graphics/image":29,"./graphics/particles":30,"./graphics/sprite":32,"./graphics/sprite-animation":31,"./graphics/text":33,"./graphics/viewport":34,"./graphics/webgl":35,"./isometric/diamond-iso":36,"./isometric/isometric":37,"./sound/sound":38,"./spatial/2d":39,"./spatial/collision":40,"./spatial/math":41,"./spatial/rect-manager":42,"./spatial/spatial-grid":43}],18:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.c("DebugCanvas",{init:function(){this.requires("2D"),d.DebugCanvas.context||d.DebugCanvas.init(),d.DebugCanvas.add(this),this._debug={alpha:1,lineWidth:1},this.bind("RemoveComponent",this.onDebugRemove),this.bind("Remove",this.onDebugDestroy)},onDebugRemove:function(a){"DebugCanvas"===a&&d.DebugCanvas.remove(this)},onDebugDestroy:function(a){d.DebugCanvas.remove(this)},debugAlpha:function(a){return this._debug.alpha=a,this},debugFill:function(a){return"undefined"==typeof a&&(a="red"),this._debug.fillStyle=a,this},debugStroke:function(a){return"undefined"==typeof a&&(a="red"),this._debug.strokeStyle=a,this},debugDraw:function(a){var b=a.globalAlpha,c=this._debug;c.alpha&&(a.globalAlpha=this._debug.alpha),c.strokeStyle&&(a.strokeStyle=c.strokeStyle),c.lineWidth&&(a.lineWidth=c.lineWidth),c.fillStyle&&(a.fillStyle=c.fillStyle),this.trigger("DebugDraw"),a.globalAlpha=b}}),d.c("DebugRectangle",{init:function(){this.requires("2D, DebugCanvas")},debugRectangle:function(a){return this.debugRect=a,this.unbind("DebugDraw",this.drawDebugRect),this.bind("DebugDraw",this.drawDebugRect),this},drawDebugRect:function(){var a=d.DebugCanvas.context,b=this.debugRect;null!==b&&void 0!==b&&b._h&&b._w&&(this._debug.fillStyle&&a.fillRect(b._x,b._y,b._w,b._h),this._debug.strokeStyle&&a.strokeRect(b._x,b._y,b._w,b._h))}}),d.c("VisibleMBR",{init:function(){this.requires("DebugRectangle").debugFill("purple").bind("EnterFrame",this._assignRect)},_assignRect:function(){this._mbr?this.debugRectangle(this._mbr):this.debugRectangle(this)}}),d.c("DebugPolygon",{init:function(){this.requires("2D, DebugCanvas")},debugPolygon:function(a){return this.polygon=a,this.unbind("DebugDraw",this.drawDebugPolygon),this.bind("DebugDraw",this.drawDebugPolygon),this},drawDebugPolygon:function(){if("undefined"!=typeof this.polygon){var a=d.DebugCanvas.context;a.beginPath();for(var b=this.polygon.points,c=b.length,e=0;c>e;e+=2)a.lineTo(b[e],b[e+1]);a.closePath(),this._debug.fillStyle&&a.fill(),this._debug.strokeStyle&&a.stroke()}}}),d.c("WiredHitBox",{init:function(){this.requires("DebugPolygon").debugStroke("red").matchHitBox(),this.bind("NewHitbox",this.matchHitBox)},matchHitBox:function(){this.debugPolygon(this.map)}}),d.c("SolidHitBox",{init:function(){this.requires("Collision, DebugPolygon").debugFill("orange").debugAlpha(.7).matchHitBox(),this.bind("NewHitbox",this.matchHitBox)},matchHitBox:function(){this.debugPolygon(this.map)}}),d.c("WiredAreaMap",{init:function(){this.requires("DebugPolygon").debugStroke("green").matchAreaMap(),this.bind("NewAreaMap",this.matchAreaMap)},matchAreaMap:function(){this.debugPolygon(this.mapArea)}}),d.c("SolidAreaMap",{init:function(){this.requires("DebugPolygon").debugFill("lime").debugAlpha(.7).matchAreaMap(),this.bind("NewAreaMap",this.matchAreaMap)},matchAreaMap:function(){this.debugPolygon(this.mapArea)}}),d.DebugCanvas={context:null,entities:[],onetimeEntities:[],add:function(a){this.entities.push(a)},remove:function(a){for(var b=this.entities,c=b.length-1;c>=0;c--)b[c]==a&&b.splice(c,1)},init:function(){if(!d.DebugCanvas.context){if(!d.support.canvas)return d.trigger("NoCanvas"),void d.stop();var a;a=e.createElement("canvas"),a.width=d.viewport.width,a.height=d.viewport.height,a.style.position="absolute",a.style.left="0px",a.style.top="0px",a.id="debug-canvas",a.style.zIndex=1e5,d.stage.elem.appendChild(a),d.DebugCanvas.context=a.getContext("2d"),d.DebugCanvas._canvas=a}d.unbind("RenderScene",d.DebugCanvas.renderScene),d.bind("RenderScene",d.DebugCanvas.renderScene)},renderScene:function(a){a=a||d.viewport.rect();var b,c=d.DebugCanvas.entities,e=0,f=c.length,g=d.DebugCanvas.context,h=d.viewport;for(g.setTransform(h._scale,0,0,h._scale,Math.round(h._x*h._scale),Math.round(h._y*h._scale)),g.clearRect(a._x,a._y,a._w,a._h);f>e;e++)b=c[e],b.debugDraw(g)}}},{"../core/core.js":7}],19:[function(a,b,c){var d=a("../core/core.js");d.extend({loggingEnabled:!0,log:function(){d.loggingEnabled&&console&&console.log&&console.log.apply(console,arguments)},error:function(){d.loggingEnabled&&console&&console.error&&console.error.apply(console,arguments)}})},{"../core/core.js":7}],20:[function(a,b,c){var d=a("../core/core.js");d.extend({canvasLayer:{_dirtyRects:[],_changedObjs:[],layerCount:0,_dirtyViewport:!1,_sort:function(a,b){return a._globalZ-b._globalZ},add:function(a){this._changedObjs.push(a)},context:null,_canvas:null,init:function(){if(!d.support.canvas)return d.trigger("NoCanvas"),void d.stop();this._dirtyRects=[],this._changedObjs=[],this.layerCount=0;var a;a=document.createElement("canvas"),a.width=d.viewport.width,a.height=d.viewport.height,a.style.position="absolute",a.style.left="0px",a.style.top="0px";d.canvasLayer;d.stage.elem.appendChild(a),this.context=a.getContext("2d"),this._canvas=a;var b=d.viewport._scale;1!=b&&a.scale(b,b),this._setPixelart(d._pixelartEnabled),d.uniqueBind("PixelartSet",this._setPixelart),d.uniqueBind("RenderScene",this._render),d.uniqueBind("ViewportResize",this._resize),d.bind("InvalidateViewport",function(){d.canvasLayer._dirtyViewport=!0})},_render:function(){var a=d.canvasLayer,b=a._dirtyViewport,c=a._changedObjs.length,e=a.context;if(c||b){if(b){var f=d.viewport;e.setTransform(f._scale,0,0,f._scale,Math.round(f._x*f._scale),Math.round(f._y*f._scale))}c/a.layerCount>.6||b?a._drawAll():a._drawDirty(),a._clean()}},_drawDirty:function(){var a,b,c,e,f,g,h=this._changedObjs,i=h.length,j=this._dirtyRects,k=d.rectManager,l=k.overlap,m=this.context,n=[],o=[];for(a=0;i>a;a++)this._createDirty(h[a]);for(k.mergeSet(j),i=j.length,a=0;i>a;++a)if(e=j[a],n.length=0,o.length=0,e){for(e._w=e._x+e._w,e._h=e._y+e._h,e._x=e._x>0?0|e._x:(0|e._x)-1,e._y=e._y>0?0|e._y:(0|e._y)-1,e._w-=e._x,e._h-=e._y,e._w=e._w===(0|e._w)?e._w:(0|e._w)+1,e._h=e._h===(0|e._h)?e._h:(0|e._h)+1,c=d.map.search(e,!1),m.clearRect(e._x,e._y,e._w,e._h),m.save(),m.beginPath(),m.rect(e._x,e._y,e._w,e._h),m.clip(),b=0,f=c.length;f>b;++b)g=c[b],!n[g[0]]&&g._visible&&g.__c.Canvas&&(n[g[0]]=!0,o.push(g));for(o.sort(this._sort),b=0,f=o.length;f>b;++b){g=o[b];var p=g._mbr||g;l(p,e)&&g.draw(),g._changed=!1}m.closePath(),m.restore()}if(d.canvasLayer.debugDirty===!0)for(m.strokeStyle="red",a=0,i=j.length;i>a;++a)e=j[a],m.strokeRect(e._x,e._y,e._w,e._h)},_drawAll:function(a){a=a||d.viewport.rect();var b,c=d.map.search(a),e=0,f=c.length,g=this.context;for(g.clearRect(a._x,a._y,a._w,a._h),c.sort(this._sort);f>e;e++)b=c[e],b._visible&&b.__c.Canvas&&(b.draw(),b._changed=!1)},debug:function(){d.log(this._changedObjs)},_clean:function(){var a,b,c,d,e=this._changedObjs;for(c=0,d=e.length;d>c;c++)b=e[c],a=b._mbr||b,"undefined"==typeof b.staleRect&&(b.staleRect={}),b.staleRect._x=a._x,b.staleRect._y=a._y,b.staleRect._w=a._w,b.staleRect._h=a._h,b._changed=!1;e.length=0,this._dirtyRects.length=0,this._dirtyViewport=!1},_createDirty:function(a){var b=a._mbr||a,c=this._dirtyRects,e=d.rectManager;if(a.staleRect){if(e.overlap(a.staleRect,b))return e.merge(a.staleRect,b,a.staleRect),void c.push(a.staleRect);c.push(a.staleRect)}a.currentRect._x=b._x,a.currentRect._y=b._y,a.currentRect._w=b._w,a.currentRect._h=b._h,c.push(a.currentRect)},_resize:function(){var a=d.canvasLayer._canvas;a.width=d.viewport.width,a.height=d.viewport.height},_setPixelart:function(a){var b=d.canvasLayer.context;b.imageSmoothingEnabled=!a,b.mozImageSmoothingEnabled=!a,b.webkitImageSmoothingEnabled=!a,b.oImageSmoothingEnabled=!a,b.msImageSmoothingEnabled=!a}}})},{"../core/core.js":7}],21:[function(a,b,c){var d=a("../core/core.js");d.c("Canvas",{init:function(){var a=d.canvasLayer;a.context||a.init(),this._drawLayer=a,this._drawContext=a.context,a.layerCount++,this.currentRect={},this._changed=!0,a.add(this),this.bind("Invalidate",function(b){this._changed===!1&&(this._changed=!0,a.add(this))}),this.bind("Remove",function(){this._drawLayer.layerCount--,this._changed=!0,this._drawLayer.add(this)})},drawVars:{type:"canvas",pos:{},ctx:null,coord:[0,0,0,0],co:{x:0,y:0,w:0,h:0}},draw:function(a,b,c,d,e){if(this.ready){4===arguments.length&&(e=d,d=c,c=b,b=a,a=this._drawContext);var f=this.drawVars.pos;f._x=this._x+(b||0),f._y=this._y+(c||0),f._w=d||this._w,f._h=e||this._h,context=a||this._drawContext,coord=this.__coord||[0,0,0,0];var g=this.drawVars.co;g.x=coord[0]+(b||0),g.y=coord[1]+(c||0),g.w=d||coord[2],g.h=e||coord[3],(this._flipX||this._flipY||this._rotation)&&context.save(),0!==this._rotation&&(context.translate(this._origin.x+this._x,this._origin.y+this._y),f._x=-this._origin.x,f._y=-this._origin.y,context.rotate(this._rotation%360*(Math.PI/180))),(this._flipX||this._flipY)&&(context.scale(this._flipX?-1:1,this._flipY?-1:1),this._flipX&&(f._x=-(f._x+f._w)),this._flipY&&(f._y=-(f._y+f._h)));var h;return this._alpha<1&&(h=context.globalAlpha,context.globalAlpha=this._alpha),this.drawVars.ctx=context,this.trigger("Draw",this.drawVars),(0!==this._rotation||this._flipX||this._flipY)&&context.restore(),h&&(context.globalAlpha=h),this}}})},{"../core/core.js":7}],22:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.extend({assignColor:function(){function a(a){return a._red=a._blue=a._green=0,a}function b(a){var b=a.toString(16);return 1==b.length&&(b="0"+b),b}function c(a,c,d){return"#"+b(a)+b(c)+b(d)}function d(b,c){var d;if(7===b.length)d=2;else{if(4!==b.length)return a(c);d=1}return c._red=parseInt(b.substr(1,d),16),c._green=parseInt(b.substr(1+d,d),16),c._blue=parseInt(b.substr(1+2*d,d),16),c}function f(b,c){var d=l.exec(b);return null===d||4!=d.length&&5!=d.length?a(c):(c._red=Math.round(parseFloat(d[1])),c._green=Math.round(parseFloat(d[2])),c._blue=Math.round(parseFloat(d[3])),d[4]&&(c._strength=parseFloat(d[4])),c)}function g(a,b){if("undefined"==typeof k[a]){j===!1&&(window.document.body.appendChild(i),j=!0),i.style.color=a;var e=window.getComputedStyle(i).color;f(e,b),k[a]=c(b._red,b._green,b._blue)}else d(k[a],b);return b}function h(a){return"rgba("+a._red+", "+a._green+", "+a._blue+", "+a._strength+")"}var i=e.createElement("div");i.style.display="none";var j=!1,k={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#00ff00",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",orange:"#ffa500",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},l=/rgba?\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,?\s*([0-9.]+)?\)/;return function(a,b){b=b||{},a=a.trim().toLowerCase();var c=null;c="#"===a[0]?d(a,b):"r"===a[0]&&"g"===a[1]&&"b"===a[2]?f(a,b):g(a,b),b._strength=b._strength||1,b._color=h(b)}}()});var f="attribute vec2 aPosition;\nattribute vec3 aOrientation;\nattribute vec2 aLayer;\nattribute vec4 aColor;\n\nvarying lowp vec4 vColor;\n\nuniform vec4 uViewport;\n\nmat4 viewportScale = mat4(2.0 / uViewport.z, 0, 0, 0, 0, -2.0 / uViewport.w, 0,0, 0, 0,1,0, -1,+1,0,1);\nvec4 viewportTranslation = vec4(uViewport.xy, 0, 0);\n\nvoid main() {\n vec2 pos = aPosition;\n vec2 entityOrigin = aOrientation.xy;\n mat2 entityRotationMatrix = mat2(cos(aOrientation.z), sin(aOrientation.z), -sin(aOrientation.z), cos(aOrientation.z));\n\n pos = entityRotationMatrix * (pos - entityOrigin) + entityOrigin;\n gl_Position = viewportScale * (viewportTranslation + vec4(pos, 1.0/(1.0+exp(aLayer.x) ), 1) );\n vColor = vec4(aColor.rgb*aColor.a*aLayer.y, aColor.a*aLayer.y);\n}",g="precision mediump float;\nvarying lowp vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}",h=[{name:"aPosition",width:2},{name:"aOrientation",width:3},{name:"aLayer",width:2},{name:"aColor",width:4}];d.c("Color",{_red:0,_green:0,_blue:0,_strength:1,_color:"",ready:!0,init:function(){this.bind("Draw",this._drawColor),this.has("WebGL")&&this._establishShader("Color",g,f,h),this.trigger("Invalidate")},remove:function(){this.unbind("Draw",this._drawColor),this.has("DOM")&&(this._element.style.backgroundColor="transparent"),this.trigger("Invalidate")},_drawColor:function(a){this._color&&("DOM"===a.type?(a.style.backgroundColor=this._color,a.style.lineHeight=0):"canvas"===a.type?(a.ctx.fillStyle=this._color,a.ctx.fillRect(a.pos._x,a.pos._y,a.pos._w,a.pos._h)):"webgl"===a.type&&a.program.writeVector("aColor",this._red/255,this._green/255,this._blue/255,this._strength))},color:function(a){return 0===arguments.length?this._color:(arguments.length>=3?(this._red=arguments[0],this._green=arguments[1],this._blue=arguments[2],"number"==typeof arguments[3]&&(this._strength=arguments[3])):(d.assignColor(a,this),"number"==typeof arguments[1]&&(this._strength=arguments[1])),this._color="rgba("+this._red+", "+this._green+", "+this._blue+", "+this._strength+")",this.trigger("Invalidate"),this)}})},{"../core/core.js":7}],23:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.extend({domHelper:{innerPosition:function(a){var b=a.getBoundingClientRect(),c=b.left+(window.pageXOffset?window.pageXOffset:e.body.scrollLeft),d=b.top+(window.pageYOffset?window.pageYOffset:e.body.scrollTop),f=parseInt(this.getStyle(a,"border-left-width")||0,10)||parseInt(this.getStyle(a,"borderLeftWidth")||0,10)||0,g=parseInt(this.getStyle(a,"border-top-width")||0,10)||parseInt(this.getStyle(a,"borderTopWidth")||0,10)||0;return c+=f,d+=g,{x:c,y:d}},getStyle:function(a,b){var c;return a.currentStyle?c=a.currentStyle[this.camelize(b)]:window.getComputedStyle&&(c=e.defaultView.getComputedStyle(a,null).getPropertyValue(this.csselize(b))),c},camelize:function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},csselize:function(a){return a.replace(/[A-Z]/g,function(a){return a?"-"+a.toLowerCase():""})},translate:function(a,b){var c=e.documentElement,f=e.body;return{x:(a-d.stage.x+(c&&c.scrollLeft||f&&f.scrollLeft||0))/d.viewport._scale-d.viewport._x,y:(b-d.stage.y+(c&&c.scrollTop||f&&f.scrollTop||0))/d.viewport._scale-d.viewport._y}}}})},{"../core/core.js":7}],24:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.extend({domLayer:{_changedObjs:[],_dirtyViewport:!1,_div:null,init:function(){this._changedObjs=[],this._dirtyViewport=!1;var a=this._div=e.createElement("div");d.stage.elem.appendChild(a),a.style.position="absolute",a.style.zIndex="1",a.style.transformStyle="preserve-3d",d.uniqueBind("RenderScene",this._render),d.uniqueBind("PixelartSet",this._setPixelArt),d.uniqueBind("InvalidateViewport",function(){d.domLayer._dirtyViewport=!0})},_setPixelArt:function(a){var b=d.domLayer._div.style,c=d.domHelper.camelize;a?(b[c("image-rendering")]="optimizeSpeed",b[c("image-rendering")]="-moz-crisp-edges",b[c("image-rendering")]="-o-crisp-edges",b[c("image-rendering")]="-webkit-optimize-contrast",b[c("-ms-interpolation-mode")]="nearest-neighbor",b[c("image-rendering")]="optimize-contrast",b[c("image-rendering")]="pixelated",b[c("image-rendering")]="crisp-edges"):(b[c("image-rendering")]="optimizeQuality",b[c("-ms-interpolation-mode")]="bicubic",b[c("image-rendering")]="auto")},debug:function(){d.log(this._changedObjs)},_render:function(){var a=d.domLayer,b=a._changedObjs;if(a._dirtyViewport&&(a._setViewport(),a._dirtyViewport=!1),b.length){for(var c=0,e=b.length;e>c;++c)b[c].draw()._changed=!1;b.length=0}},add:function(a){this._changedObjs.push(a)},_setViewport:function(){var a=d.domLayer._div.style,b=d.viewport;a.transform=a[d.support.prefix+"Transform"]="scale("+b._scale+", "+b._scale+")",a.left=Math.round(b._x*b._scale)+"px",a.top=Math.round(b._y*b._scale)+"px",a.zIndex=10}}})},{"../core/core.js":7}],25:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.c("DOM",{_element:null,_cssStyles:null,avoidCss3dTransforms:!1,init:function(){var a=d.domLayer;a._div||a.init(),this._drawLayer=a,this._cssStyles={visibility:"",left:"",top:"",width:"",height:"",zIndex:"",opacity:"",transformOrigin:"",transform:""},this._element=e.createElement("div"),a._div.appendChild(this._element),this._element.style.position="absolute",this._element.id="ent"+this[0],this.bind("Invalidate",this._invalidateDOM),this.bind("NewComponent",this._updateClass),this.bind("RemoveComponent",this._removeClass),this._invalidateDOM()},remove:function(){this.undraw(),this.unbind("NewComponent",this._updateClass),this.unbind("RemoveComponent",this._removeClass),this.unbind("Invalidate",this._invalidateDOM)},getDomId:function(){return this._element.id},_removeClass:function(a){var b=0,c=this.__c,d="";for(b in c)b!=a&&(d+=" "+b);d=d.substr(1),this._element.className=d},_updateClass:function(){var a=0,b=this.__c,c="";for(a in b)c+=" "+a;c=c.substr(1),this._element.className=c},_invalidateDOM:function(){this._changed||(this._changed=!0,this._drawLayer.add(this))},DOM:function(a){return a&&a.nodeType&&(this.undraw(),this._element=a,this._element.style.position="absolute"),this},draw:function(){var a=this._element.style,b=this.__coord||[0,0,0,0],c={x:b[0],y:b[1],w:b[2],h:b[3]},e=d.support.prefix,f=[];if(this._cssStyles.visibility!==this._visible&&(this._cssStyles.visibility=this._visible,this._visible?a.visibility="visible":a.visibility="hidden"),d.support.css3dtransform&&!this.avoidCss3dTransforms?f.push("translate3d("+~~this._x+"px,"+~~this._y+"px,0)"):(this._cssStyles.left!==this._x&&(this._cssStyles.left=this._x,a.left=~~this._x+"px"),this._cssStyles.top!==this._y&&(this._cssStyles.top=this._y,a.top=~~this._y+"px")),this._cssStyles.width!==this._w&&(this._cssStyles.width=this._w,a.width=~~this._w+"px"),this._cssStyles.height!==this._h&&(this._cssStyles.height=this._h,a.height=~~this._h+"px"),this._cssStyles.zIndex!==this._z&&(this._cssStyles.zIndex=this._z,a.zIndex=this._z),this._cssStyles.opacity!==this._alpha&&(this._cssStyles.opacity=this._alpha,a.opacity=this._alpha,a[e+"Opacity"]=this._alpha),this._mbr){var g=this._origin.x+"px "+this._origin.y+"px";a.transformOrigin=g,a[e+"TransformOrigin"]=g,d.support.css3dtransform?f.push("rotateZ("+this._rotation+"deg)"):f.push("rotate("+this._rotation+"deg)")}return this._flipX&&f.push("scaleX(-1)"),this._flipY&&f.push("scaleY(-1)"),this._cssStyles.transform!=f.join(" ")&&(this._cssStyles.transform=f.join(" "),a.transform=this._cssStyles.transform,a[e+"Transform"]=this._cssStyles.transform),this.trigger("Draw",{style:a,type:"DOM",co:c}),this},undraw:function(){var a=this._element;return a&&null!==a.parentNode&&a.parentNode.removeChild(a),this},css:function(a,b){var c,e,f=this._element,g=f.style;if("object"==typeof a)for(c in a)a.hasOwnProperty(c)&&(e=a[c],"number"==typeof e&&(e+="px"),g[d.domHelper.camelize(c)]=e);else{if(!b)return d.domHelper.getStyle(f,a);"number"==typeof b&&(b+="px"),g[d.domHelper.camelize(a)]=b}return this.trigger("Invalidate"),this}})},{"../core/core.js":7}],26:[function(a,b,c){var d=a("../core/core.js");d.extend({_pixelartEnabled:!1,pixelart:function(a){d._pixelartEnabled=a,d.trigger("PixelartSet",a)}})},{"../core/core.js":7}],27:[function(a,b,c){var d=a("../core/core.js"),e=d.TextureManager=function(a,b){this.gl=a,this.webgl=b,this.max_units=a.getParameter(a.MAX_COMBINED_TEXTURE_IMAGE_UNITS),this.bound_textures=[],this.registered_textures={},this.active=null};e.prototype={reset:function(){for(var a,b=0;b100?100:a.sharpness<0?0:a.sharpness,a.sizeSmall=~~(a.size/200*a.sharpness);var f=[this.startColour[0]+this.startColourRandom[0]*this.RANDM1TO1(),this.startColour[1]+this.startColourRandom[1]*this.RANDM1TO1(),this.startColour[2]+this.startColourRandom[2]*this.RANDM1TO1(),this.startColour[3]+this.startColourRandom[3]*this.RANDM1TO1()],g=[this.endColour[0]+this.endColourRandom[0]*this.RANDM1TO1(),this.endColour[1]+this.endColourRandom[1]*this.RANDM1TO1(),this.endColour[2]+this.endColourRandom[2]*this.RANDM1TO1(),this.endColour[3]+this.endColourRandom[3]*this.RANDM1TO1()];a.colour=f,a.deltaColour[0]=(g[0]-f[0])/a.timeToLive,a.deltaColour[1]=(g[1]-f[1])/a.timeToLive,a.deltaColour[2]=(g[2]-f[2])/a.timeToLive,a.deltaColour[3]=(g[3]-f[3])/a.timeToLive},update:function(){if(this.active&&this.emissionRate>0){var a=1/this.emissionRate;for(this.emitCounter++;this.particleCounta;)this.addParticle(),this.emitCounter-=a;this.elapsedFrames++,-1!=this.duration&&this.duration0){c.direction=this.vectorHelpers.add(c.direction,this.gravity),c.position=this.vectorHelpers.add(c.position,c.direction),c.position=this.vectorHelpers.add(c.position,this.viewportDelta),this.jitter&&(c.position.x+=this.jitter*this.RANDM1TO1(),c.position.y+=this.jitter*this.RANDM1TO1()),c.timeToLive--;var d=c.colour[0]+=c.deltaColour[0],e=c.colour[1]+=c.deltaColour[1],f=c.colour[2]+=c.deltaColour[2],g=c.colour[3]+=c.deltaColour[3];b=[],b.push("rgba("+(d>255?255:0>d?0:~~d)),b.push(e>255?255:0>e?0:~~e),b.push(f>255?255:0>f?0:~~f),b.push((g>1?1:0>g?0:g.toFixed(2))+")"),c.drawColour=b.join(","),this.fastMode||(b[3]="0)",c.drawColourEnd=b.join(",")),this.particleIndex++}else this.particleIndex!=this.particleCount-1&&(this.particles[this.particleIndex]=this.particles[this.particleCount-1]),this.particleCount--;var h={};h._x=~~c.position.x,h._y=~~c.position.y,h._w=c.size,h._h=c.size,this.register.push(h)}},stop:function(){this.active=!1,this.elapsedFrames=0,this.emitCounter=0,this.parentEntity.trigger("ParticleEnd")},render:function(a){for(var b=0,c=this.particleCount;c>b;b++){var e=this.particles[b],f=e.size,g=f>>1;if(!(e.position.x+f<0||e.position.y+f<0||e.position.x-f>d.viewport.width||e.position.y-f>d.viewport.height)){var h=~~e.position.x,i=~~e.position.y;if(this.fastMode)a.fillStyle=e.drawColour;else{var j=a.createRadialGradient(h+g,i+g,e.sizeSmall,h+g,i+g,g);j.addColorStop(0,e.drawColour),j.addColorStop(.9,e.drawColourEnd),a.fillStyle=j}a.fillRect(h,i,f,f)}}},particle:function(a){this.position=a.create(0,0),this.direction=a.create(0,0),this.size=0,this.sizeSmall=0,this.timeToLive=0,this.colour=[],this.drawColour="",this.deltaColour=[],this.sharpness=0},vectorHelpers:{create:function(a,b){return{x:a,y:b}},multiply:function(a,b){return a.x*=b,a.y*=b,a},add:function(a,b){return a.x+=b.x,a.y+=b.y,a}}}})},{"../core/core.js":7}],31:[function(a,b,c){var d=a("../core/core.js");d.c("SpriteAnimation",{_reels:null,_currentReelId:null,_currentReel:null,_isPlaying:!1,animationSpeed:1,init:function(){this._reels={}},reel:function(a,b,c,e,f){if(0===arguments.length)return this._currentReelId;if(1===arguments.length&&"string"==typeof a){if("undefined"==typeof this._reels[a])throw"The specified reel "+a+" is undefined.";return this.pauseAnimation(),this._currentReelId!==a&&(this._currentReelId=a,this._currentReel=this._reels[a],this._updateSprite(),this.trigger("ReelChange",this._currentReel)),this}var g,h,i;if(g={id:a,frames:[],currentFrame:0,easing:new d.easing(b),defaultLoops:1},g.duration=g.easing.duration,"number"==typeof c)if(h=c,i=e,f>=0)for(;c+f>h;h++)g.frames.push([h,i]);else for(;h>c+f;h--)g.frames.push([h,i]);else{if(3!==arguments.length||"object"!=typeof c)throw"Urecognized arguments. Please see the documentation for 'reel(...)'.";g.frames=c}return this._reels[a]=g,this},animate:function(a,b){"string"==typeof a&&this.reel(a);var c=this._currentReel;if("undefined"==typeof c||null===c)throw"No reel is specified, and there is no currently active reel.";return this.pauseAnimation(),"undefined"==typeof b&&(b="number"==typeof a?a:1),c.easing.reset(),this.loops(b),this._setFrame(0),this.bind("EnterFrame",this._animationTick),this._isPlaying=!0,this.trigger("StartAnimation",c),this},resumeAnimation:function(){return this._isPlaying===!1&&null!==this._currentReel&&(this.bind("EnterFrame",this._animationTick),this._isPlaying=!0,this._currentReel.easing.resume(),this.trigger("StartAnimation",this._currentReel)),this},pauseAnimation:function(){return this._isPlaying===!0&&(this.unbind("EnterFrame",this._animationTick),this._isPlaying=!1,this._reels[this._currentReelId].easing.pause()),this},resetAnimation:function(){var a=this._currentReel;if(null===a)throw"No active reel to reset.";return this.reelPosition(0),a.easing.repeat(a.defaultLoops),this},loops:function(a){return 0===arguments.length?null!==this._currentReel?this._currentReel.easing.loops:0:(null!==this._currentReel&&(0>a&&(a=1/0),this._currentReel.easing.repeat(a),this._currentReel.defaultLoops=a),this)},reelPosition:function(a){if(null===this._currentReel)throw"No active reel.";if(0===arguments.length)return this._currentReel.currentFrame;var b,c=this._currentReel.frames.length;if("end"===a&&(a=c-1),1>a&&a>0)b=a,a=Math.floor(c*b);else{if(a!==Math.floor(a))throw"Position "+a+" is invalid.";0>a&&(a=c-1+a),b=a/c}return a=Math.min(a,c-1),a=Math.max(a,0),this._setProgress(b),this._setFrame(a),this},_animationTick:function(a){var b=this._reels[this._currentReelId];b.easing.tick(a.dt*this.animationSpeed);var c=b.easing.value(),d=Math.min(Math.floor(b.frames.length*c),b.frames.length-1);this._setFrame(d),b.easing.complete===!0&&(this.pauseAnimation(),this.trigger("AnimationEnd",this._currentReel))},_setFrame:function(a){var b=this._currentReel;a!==b.currentFrame&&(b.currentFrame=a,this._updateSprite(),this.trigger("FrameChange",b))},_updateSprite:function(){var a=this._currentReel,b=a.frames[a.currentFrame];this.sprite(b[0],b[1])},_setProgress:function(a,b){this._currentReel.easing.setProgress(a,b)},isPlaying:function(a){return this._isPlaying?a?this._currentReelId===a:!!this._currentReelId:!1},getReel:function(a){if(0===arguments.length){if(!this._currentReelId)return null;a=this._currentReelId}return this._reels[a]}})},{"../core/core.js":7}],32:[function(a,b,c){var d=a("../core/core.js"),e="attribute vec2 aPosition;\nattribute vec3 aOrientation;\nattribute vec2 aLayer;\nattribute vec2 aTextureCoord;\n\nvarying mediump vec3 vTextureCoord;\n\nuniform vec4 uViewport;\nuniform mediump vec2 uTextureDimensions;\n\nmat4 viewportScale = mat4(2.0 / uViewport.z, 0, 0, 0, 0, -2.0 / uViewport.w, 0,0, 0, 0,1,0, -1,+1,0,1);\nvec4 viewportTranslation = vec4(uViewport.xy, 0, 0);\n\nvoid main() {\n vec2 pos = aPosition;\n vec2 entityOrigin = aOrientation.xy;\n mat2 entityRotationMatrix = mat2(cos(aOrientation.z), sin(aOrientation.z), -sin(aOrientation.z), cos(aOrientation.z));\n \n pos = entityRotationMatrix * (pos - entityOrigin) + entityOrigin ;\n gl_Position = viewportScale * (viewportTranslation + vec4(pos, 1.0/(1.0+exp(aLayer.x) ), 1) );\n vTextureCoord = vec3(aTextureCoord, aLayer.y);\n}",f="varying mediump vec3 vTextureCoord;\n \nuniform sampler2D uSampler;\nuniform mediump vec2 uTextureDimensions;\n\nvoid main(void) {\n highp vec2 coord = vTextureCoord.xy / uTextureDimensions;\n mediump vec4 base_color = texture2D(uSampler, coord);\n gl_FragColor = vec4(base_color.rgb*base_color.a*vTextureCoord.z, base_color.a*vTextureCoord.z);\n}",g=[{name:"aPosition",width:2},{name:"aOrientation",width:3},{name:"aLayer",width:2},{name:"aTextureCoord",width:2}];d.extend({sprite:function(a,b,c,h,i,j,k){var l,m,n;"string"==typeof a&&(j=i,i=h,h=b,c=a,a=1,b=1),"string"==typeof b&&(j=i,i=h,h=c,c=b,b=a),!j&&i&&(j=i),i=parseInt(i||0,10),j=parseInt(j||0,10);var o=function(){this.ready=!0,this.trigger("Invalidate")};n=d.asset(c),n||(n=new Image,n.src=c,d.asset(c,n),n.onload=function(){for(var a in h)d(a).each(o)});var p=function(){this.requires("2D, Sprite"),this.__trim=[0,0,0,0],this.__image=c,this.__coord=[this.__coord[0],this.__coord[1],this.__coord[2],this.__coord[3]],this.__tile=a,this.__tileh=b,this.__padding=[i,j],this.__padBorder=k,this.sprite(this.__coord[0],this.__coord[1],this.__coord[2],this.__coord[3]),this.img=n,this.img.complete&&this.img.width>0&&(this.ready=!0,this.trigger("Invalidate")),this.w=this.__coord[2],this.h=this.__coord[3],this.has("WebGL")&&(this._establishShader(this.__image,f,e,g),this.program.setTexture(this.webgl.makeTexture(this.__image,this.img,!1)))};for(l in h)h.hasOwnProperty(l)&&(m=h[l],d.c(l,{ready:!1,__coord:[m[0],m[1],m[2]||1,m[3]||1],init:p}));return this}}),d.c("Sprite",{__image:"",__tile:0,__tileh:0,__padding:null,__trim:null,img:null,ready:!1,init:function(){this.__trim=[0,0,0,0],this.bind("Draw",this._drawSprite)},remove:function(){this.unbind("Draw",this._drawSprite)},_drawSprite:function(a){var b=a.co,c=a.pos,d=a.ctx;if("canvas"===a.type)d.drawImage(this.img,b.x,b.y,b.w,b.h,c._x,c._y,c._w,c._h);else if("DOM"===a.type){var e=this._h/b.h,f=this._w/b.w,g=this._element.style,h=g.backgroundColor;"initial"===h&&(h="");var i=h+" url('"+this.__image+"') no-repeat";i!==g.background&&(g.background=i),g.backgroundPosition="-"+b.x*f+"px -"+b.y*e+"px",(1!=e||1!=f)&&(g.backgroundSize=this.img.width*f+"px "+this.img.height*e+"px")}else"webgl"===a.type&&a.program.writeVector("aTextureCoord",b.x,b.y,b.x,b.y+b.h,b.x+b.w,b.y,b.x+b.w,b.y+b.h)},sprite:function(a,b,c,d){return this.__coord=this.__coord||[0,0,0,0],this.__coord[0]=a*(this.__tile+this.__padding[0])+(this.__padBorder?this.__padding[0]:0)+this.__trim[0],this.__coord[1]=b*(this.__tileh+this.__padding[1])+(this.__padBorder?this.__padding[1]:0)+this.__trim[1],"undefined"!=typeof c&&"undefined"!=typeof d&&(this.__coord[2]=this.__trim[2]||c*this.__tile||this.__tile,this.__coord[3]=this.__trim[3]||d*this.__tileh||this.__tileh),this.trigger("Invalidate"),this},crop:function(a,b,c,d){var e=this._mbr||this.pos();return this.__trim=[],this.__trim[0]=a,this.__trim[1]=b,this.__trim[2]=c,this.__trim[3]=d,this.__coord[0]+=a,this.__coord[1]+=b,this.__coord[2]=c,this.__coord[3]=d,this._w=c,this._h=d,this.trigger("Invalidate",e),this}})},{"../core/core.js":7}],33:[function(a,b,c){var d=a("../core/core.js");d.c("Text",{_text:"",defaultSize:"10px",defaultFamily:"sans-serif",defaultVariant:"normal",defaultLineHeight:"normal",ready:!0,init:function(){this.requires("2D"),this._textFont={type:"",weight:"",size:this.defaultSize,lineHeight:this.defaultLineHeight,family:this.defaultFamily,variant:this.defaultVariant},this.bind("Draw",function(a){var b=this._fontString();if("DOM"===a.type){var c=this._element,d=c.style;d.color=this._textColor,d.font=b,c.innerHTML=this._text}else if("canvas"===a.type){var e=a.ctx;e.save(),e.textBaseline="top",e.fillStyle=this._textColor||"rgb(0,0,0)",e.font=b,e.fillText(this._text,a.pos._x,a.pos._y),e.restore()}})},_getFontHeight:function(){var a=/([a-zA-Z]+)\b/,b={px:1,pt:4/3,pc:16,cm:96/2.54,mm:96/25.4,"in":96,em:void 0,ex:void 0};return function(c){var d=parseFloat(c),e=a.exec(c),f=e?e[1]:"px";return void 0!==b[f]?Math.ceil(d*b[f]):Math.ceil(d)}}(),text:function(a){return"undefined"==typeof a||null===a?this._text:("function"==typeof a?this._text=a.call(this):this._text=a,this.has("Canvas")&&this._resizeForCanvas(),this.trigger("Invalidate"),this)},_resizeForCanvas:function(){var a=this._drawContext;a.font=this._fontString(),this.w=a.measureText(this._text).width;var b=this._textFont.size||this.defaultSize;this.h=1.1*this._getFontHeight(b)},_fontString:function(){return this._textFont.type+" "+this._textFont.variant+" "+this._textFont.weight+" "+this._textFont.size+" / "+this._textFont.lineHeight+" "+this._textFont.family},textColor:function(a){return d.assignColor(a,this),this._textColor="rgba("+this._red+", "+this._green+", "+this._blue+", "+this._strength+")",this.trigger("Invalidate"),this},textFont:function(a,b){if(1===arguments.length){if("string"==typeof a)return this._textFont[a];if("object"==typeof a)for(var c in a)"family"==c?this._textFont[c]="'"+a[c]+"'":this._textFont[c]=a[c]}else this._textFont[a]=b;return this.has("Canvas")&&this._resizeForCanvas(),this.trigger("Invalidate"),this},unselectable:function(){return this.has("DOM")&&(this.css({"-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",cursor:"default"}),this.trigger("Invalidate")),this}})},{"../core/core.js":7}],34:[function(a,b,c){var d=a("../core/core.js"),e=window.document;d.extend({viewport:{clampToEntities:!0,_width:0,_height:0,_x:0,_y:0,_scale:1,bounds:null,scroll:function(a,b){this[a]=b,d.trigger("ViewportScroll"),d.trigger("InvalidateViewport")},rect_object:{_x:0,_y:0,_w:0,_h:0},rect:function(){return this.rect_object._x=-this._x,this.rect_object._y=-this._y,this.rect_object._w=this._width/this._scale,this.rect_object._h=this._height/this._scale,this.rect_object},pan:function(){function a(a){h.tick(a.dt);var i=h.value();d.viewport.x=(1-i)*f+i*c,d.viewport.y=(1-i)*g+i*e,d.viewport._clamp(),h.complete&&(b(),d.trigger("CameraAnimationDone"))}function b(){d.unbind("EnterFrame",a)}var c,e,f,g,h;return d._preBind("StopCamera",b),function(b,i,j,k){d.trigger("StopCamera"),"reset"!=b&&(f=d.viewport._x,g=d.viewport._y,c=f-b,e=g-i,h=new d.easing(j,k),d.uniqueBind("EnterFrame",a))}}(),follow:function(){function a(){var a=d.viewport._scale;d.viewport.scroll("_x",-(this.x+this.w/2-d.viewport.width/2/a-e*a)),d.viewport.scroll("_y",-(this.y+this.h/2-d.viewport.height/2/a-f*a)),d.viewport._clamp()}function b(){c&&(c.unbind("Move",a),c.unbind("ViewportScale",a),c.unbind("ViewportResize",a))}var c,e,f;return d._preBind("StopCamera",b),function(b,g,h){b&&b.has("2D")&&(d.trigger("StopCamera"),c=b,e="undefined"!=typeof g?g:0,f="undefined"!=typeof h?h:0,b.bind("Move",a),b.bind("ViewportScale",a),b.bind("ViewportResize",a),a.call(b))}}(),centerOn:function(a,b){var c=a.x+d.viewport.x,e=a.y+d.viewport.y,f=a.w/2,g=a.h/2,h=d.viewport.width/2/d.viewport._scale,i=d.viewport.height/2/d.viewport._scale,j=c+f-h,k=e+g-i;d.viewport.pan(j,k,b)},zoom:function(){function a(){d.unbind("EnterFrame",b)}function b(b){var e,l;k.tick(b.dt),e=Math.pow(f,k.value()),l=1===f?k.value():(1/e-1)/(1/f-1),d.viewport.scale(e*c),d.viewport.scroll("_x",g*(1-l)+h*l),d.viewport.scroll("_y",i*(1-l)+j*l),d.viewport._clamp(),k.complete&&(a(),d.trigger("CameraAnimationDone"))}d._preBind("StopCamera",a);var c,e,f,g,h,i,j,k;return function(a,l,m,n,o){return a?(arguments.length<=2&&(n=l,l=d.viewport.x-d.viewport.width,m=d.viewport.y-d.viewport.height),d.trigger("StopCamera"),c=d.viewport._scale,f=a,e=c*f,g=d.viewport.x,i=d.viewport.y,h=-(l-d.viewport.width/(2*e)),j=-(m-d.viewport.height/(2*e)),k=new d.easing(n,o),void d.uniqueBind("EnterFrame",b)):void d.viewport.scale(1)}}(),scale:function(){return function(a){this._scale=a?a:1,d.trigger("InvalidateViewport"),d.trigger("ViewportScale")}}(),mouselook:function(){var a=!1,b=!1,c={};return old={},function(e,f){if("boolean"==typeof e)return a=e,void(a?d.mouseObjs++:d.mouseObjs=Math.max(0,d.mouseObjs-1));if(a)switch(e){case"move":case"drag":if(!b)return;diff={x:f.clientX-c.x,y:f.clientY-c.y},c.x=f.clientX,c.y=f.clientY,d.viewport.x+=diff.x,d.viewport.y+=diff.y,d.viewport._clamp();break;case"start":d.trigger("StopCamera"),c.x=f.clientX,c.y=f.clientY,b=!0;break;case"stop":b=!1}}}(),_clamp:function(){if(this.clampToEntities){var a=d.clone(this.bounds)||d.map.boundaries();a.max.x*=this._scale,a.min.x*=this._scale,a.max.y*=this._scale,a.min.y*=this._scale,a.max.x-a.min.x>d.viewport.width?d.viewport.x<(-a.max.x+d.viewport.width)/this._scale?d.viewport.x=(-a.max.x+d.viewport.width)/this._scale:d.viewport.x>-a.min.x&&(d.viewport.x=-a.min.x):d.viewport.x=-1*(a.min.x+(a.max.x-a.min.x)/2-d.viewport.width/2),a.max.y-a.min.y>d.viewport.height?d.viewport.y<(-a.max.y+d.viewport.height)/this._scale?d.viewport.y=(-a.max.y+d.viewport.height)/this._scale:d.viewport.y>-a.min.y&&(d.viewport.y=-a.min.y):d.viewport.y=-1*(a.min.y+(a.max.y-a.min.y)/2-d.viewport.height/2)}},init:function(a,b,c){this._defineViewportProperties(),this._x=0,this._y=0,this._scale=1,this.bounds=null,this._width=a||window.innerWidth,this._height=b||window.innerHeight,"undefined"==typeof c&&(c="cr-stage");var f;if("string"==typeof c)f=e.getElementById(c);else{if(!("undefined"!=typeof HTMLElement?c instanceof HTMLElement:c instanceof Element))throw new TypeError("stage_elem must be a string or an HTMLElement");f=c}d.stage={x:0,y:0,fullscreen:!1,elem:f?f:e.createElement("div")},a||b||(e.body.style.overflow="hidden",d.stage.fullscreen=!0),d.addEvent(this,window,"resize",d.viewport.reload),d.addEvent(this,window,"blur",function(){d.settings.get("autoPause")&&(d._paused||d.pause())}),d.addEvent(this,window,"focus",function(){d._paused&&d.settings.get("autoPause")&&d.pause()}),d.settings.register("stageSelectable",function(a){d.stage.elem.onselectstart=a?function(){return!0}:function(){return!1}}),d.settings.modify("stageSelectable",!1),d.settings.register("stageContextMenu",function(a){d.stage.elem.oncontextmenu=a?function(){return!0}:function(){return!1}}),d.settings.modify("stageContextMenu",!1),d.settings.register("autoPause",function(){}),d.settings.modify("autoPause",!1),f||(e.body.appendChild(d.stage.elem),d.stage.elem.id=c);var g,h=d.stage.elem.style;if(h.width=this.width+"px",h.height=this.height+"px",h.overflow="hidden",d.bind("ViewportResize",function(){d.trigger("InvalidateViewport")}),d.mobile){void 0!==typeof h.webkitTapHighlightColor&&(h.webkitTapHighlightColor="rgba(0,0,0,0)");var i=e.createElement("meta"),j=e.getElementsByTagName("head")[0];i=e.createElement("meta"),i.setAttribute("name","apple-mobile-web-app-capable"),i.setAttribute("content","yes"),j.appendChild(i),d.addEvent(this,d.stage.elem,"touchmove",function(a){a.preventDefault()})}h.position="relative",g=d.domHelper.innerPosition(d.stage.elem),d.stage.x=g.x,d.stage.y=g.y,d.uniqueBind("ViewportResize",this._resize)},_resize:function(){d.stage.elem.style.width=d.viewport.width+"px",d.stage.elem.style.height=d.viewport.height+"px"},_defineViewportProperties:function(){Object.defineProperty(this,"x",{set:function(a){this.scroll("_x",a)},get:function(){return this._x},configurable:!0}),Object.defineProperty(this,"y",{set:function(a){this.scroll("_y",a)},get:function(){return this._y},configurable:!0}),Object.defineProperty(this,"width",{set:function(a){this._width=a,d.trigger("ViewportResize")},get:function(){return this._width},configurable:!0}),Object.defineProperty(this,"height",{set:function(a){this._height=a,d.trigger("ViewportResize")},get:function(){return this._height},configurable:!0})},reload:function(){var a,b=window.innerWidth,c=window.innerHeight;d.stage.fullscreen&&(this._width=b,this._height=c,d.trigger("ViewportResize")),a=d.domHelper.innerPosition(d.stage.elem),d.stage.x=a.x,d.stage.y=a.y},reset:function(){d.viewport.mouselook("stop"),d.trigger("StopCamera"),d.viewport.scroll("_x",0),d.viewport.scroll("_y",0),d.viewport.scale(1)},onScreen:function(a){return d.viewport._x+a._x+a._w>0&&d.viewport._y+a._y+a._h>0&&d.viewport._x+a._x=this.max_size)){var b=Math.min(a,this.max_size),c=new Float32Array(4*b*this.stride),d=new Uint16Array(6*b);c.set(this._attributeArray),d.set(this._indexArray),this._attributeArray=c,this._indexArray=d,this.array_size=b}},registerEntity:function(a){if(0===this._registryHoles.length){if(this._registrySize>=this.max_size)throw"Number of entities exceeds maximum limit.";this._registrySize>=this.array_size&&this.growArrays(2*this.array_size),a._glBufferIndex=this._registrySize,this._registrySize++}else a._glBufferIndex=this._registryHoles.pop()},unregisterEntity:function(a){"number"==typeof a._glBufferIndex&&this._registryHoles.push(a._glBufferIndex),a._glBufferIndex=null},resetRegistry:function(){this._maxElement=0,this._registryHoles.length=0},setCurrentEntity:function(a){this.ent_offset=4*a._glBufferIndex,this.ent=a},switchTo:function(){var a=this.context;a.useProgram(this.shader),a.bindBuffer(a.ARRAY_BUFFER,this._attributeBuffer);for(var b,c=this.attributes,e=0;ej;j++)for(var k=0;g>k;k++)i[f+e*j+k]=arguments[(g*j+k)%h+1]}},d.c("WebGL",{init:function(){d.webgl.context||d.webgl.init();var a=this.webgl=d.webgl;a.context;this._changed=!0,this.bind("Change",this._glChange)},remove:function(){this._changed=!0,this.unbind(this._glChange),this.program&&this.program.unregisterEntity(this)},_glChange:function(){this._changed===!1&&(this._changed=!0)},drawVars:{type:"webgl",pos:{},ctx:null,coord:[0,0,0,0],co:{x:0,y:0,w:0,h:0}},draw:function(a,b,c,d,e){if(this.ready){4===arguments.length&&(e=d,d=c,c=b,b=a,a=this.webgl.context);var f=this.drawVars.pos;f._x=this._x+(b||0),f._y=this._y+(c||0),f._w=d||this._w,f._h=e||this._h;var g=this.__coord||[0,0,0,0],h=this.drawVars.co;h.x=g[0]+(b||0),h.y=g[1]+(c||0),h.w=d||g[2],h.h=e||g[3],this._flipX&&(h.x=h.x+h.w,h.w=-h.w),this._flipY&&(h.y=h.y+h.h,h.h=-h.h);var i=this.webgl.context;this.drawVars.gl=i;var j=this.drawVars.program=this.program;return j.setCurrentEntity(this),j.writeVector("aPosition",this._x,this._y,this._x,this._y+this._h,this._x+this._w,this._y,this._x+this._w,this._y+this._h),j.writeVector("aOrientation",this._origin.x+this._x,this._origin.y+this._y,this._rotation*Math.PI/180),j.writeVector("aLayer",this._globalZ,this._alpha),this.trigger("Draw",this.drawVars),j.addIndices(j.ent_offset),this}},_establishShader:function(a,b,c,d){this.program=this.webgl.getProgramWrapper(a,b,c,d),this.program.registerEntity(this),this.ready=!0}}),d.extend({webgl:{context:null,changed_objects:[],_compileShader:function(a,b){var c=this.context,d=c.createShader(b);if(c.shaderSource(d,a),c.compileShader(d),!c.getShaderParameter(d,c.COMPILE_STATUS))throw c.getShaderInfoLog(d);return d},_makeProgram:function(a,b){var c=this.context,d=this._compileShader(a,c.FRAGMENT_SHADER),e=this._compileShader(b,c.VERTEX_SHADER),f=c.createProgram();if(c.attachShader(f,e),c.attachShader(f,d),c.linkProgram(f),!c.getProgramParameter(f,c.LINK_STATUS))throw"Could not initialise shaders";return f.viewport=c.getUniformLocation(f,"uViewport"),f},programs:{},getProgramWrapper:function(a,b,c,e){if(void 0===this.programs[a]){var f=this._makeProgram(b,c),g=new RenderProgramWrapper(this.context,f);g.name=a,g.initAttributes(e),g.setViewportUniforms(d.viewport),this.programs[a]=g}return this.programs[a]},makeTexture:function(a,b,c){var d=this;return d.texture_manager.makeTexture(a,b,c)},init:function(){if(!d.support.webgl)return d.trigger("NoWebGL"),void d.stop();this.changed_objects=[];var a;a=e.createElement("canvas"),a.width=d.viewport.width,a.height=d.viewport.height,a.style.position="absolute",a.style.left="0px",a.style.top="0px",d.stage.elem.appendChild(a);var b;try{b=a.getContext("webgl",{premultipliedalpha:!0})||a.getContext("experimental-webgl",{premultipliedalpha:!0}),b.viewportWidth=a.width,b.viewportHeight=a.height}catch(c){return d.trigger("NoWebGL"),void d.stop()}this.context=b,this._canvas=a,b.clearColor(0,0,0,0),b.disable(b.DEPTH_TEST),b.blendFunc(b.ONE,b.ONE_MINUS_SRC_ALPHA),b.enable(b.BLEND);var f=this;d.uniqueBind("RenderScene",f.render),d.uniqueBind("ViewportResize",f._resize),d.uniqueBind("InvalidateViewport",function(){f.dirtyViewport=!0}),d.uniqueBind("PixelartSet",f._setPixelart),f._setPixelart(d._pixelartEnabled),this.dirtyViewport=!0,this.texture_manager=new d.TextureManager(b,this)},_resize:function(){var a=d.webgl._canvas;a.width=d.viewport.width,a.height=d.viewport.height;var b=d.webgl.context;b.viewportWidth=a.width,b.viewportHeight=a.height},_setPixelart:function(a){var b=d.webgl.context;a?d.webgl.texture_filter=b.NEAREST:d.webgl.texture_filter=b.LINEAR},zsort:function(a,b){return a._globalZ-b._globalZ},visible_gl:[],render:function(a){a=a||d.viewport.rect();var b=d.webgl,c=b.context;c.viewport(0,0,c.viewportWidth,c.viewportHeight),c.clear(c.COLOR_BUFFER_BIT|c.DEPTH_BUFFER_BIT);var e=b.programs;if(b.dirtyViewport){for(var f in e)e[f].setViewportUniforms(d.viewport);b.dirtyViewport=!1}var g,h=d.map.search(a),i=0,j=h.length,k=b.visible_gl;for(k.length=0,i=0;j>i;i++)g=h[i],g._visible&&g.__c.WebGL&&g.program&&k.push(g);k.sort(b.zsort),j=k.length;var l=null;for(i=0;j>i;i++)g=k[i],l!==g.program&&(null!==l&&l.renderBatch(),l=g.program,l.index_pointer=0,l.switchTo()),g.draw(),g._changed=!1;null!==l&&l.renderBatch()}}})},{"../core/core.js":7}],36:[function(a,b,c){var d=a("../core/core.js");d.extend({diamondIso:{_tile:{width:0,height:0},getTileDimensions:function(){return{w:this._tile.width,h:this._tile.height}},_map:{width:0,height:0},_origin:{x:0,y:0},_tiles:[],getTile:function(a,b,c){return this._tiles[a][b][c]},init:function(a,b,c,d,e,f){this._tile.width=parseInt(a,10),this._tile.height=parseInt(b,10)||parseInt(a,10)/2,this._tile.r=this._tile.width/this._tile.height,this._map.width=parseInt(c,10),this._map.height=parseInt(d,10)||parseInt(c,10);for(var g=0;c>g;g++){this._tiles[g]=Array();for(var h=0;d>h;h++)this._tiles[g][h]=Array()}return this.x=parseInt(e,10)||0,this.y=parseInt(f,10)||0,this.layerZLevel=c+d+1,this},place:function(a,b,c,d){var e=this.pos2px(b,c),f=(a.tileHeight,a.h/this._tile.height);a.x=e.x,a.y=e.y-(f-2)*this._tile.height-this._tile.height*d, 12 | a.z=this.getZAtLoc(b,c,d);for(var g=0;f-2>=g;g++){var h=this._tiles[b][c][d+g];h&&h!==a&&h.destroy(),this._tiles[b][c][d+g]=a}return this},detachTile:function(a){for(var b=0;be;e++)if(this._tiles[b][c][e]&&a===this._tiles[b][c][e]){tHeight=a.h/this._tile.height;for(var f=0;f0&&e0&&fk;k++){var l=this._tiles[e+k][f+k][k];l&&d.push(l)}return d},polygon:function(a){a.requires("Collision");var b=0,c=0,e=[b-0,a.h-c-this._tile.height/2,b-this._tile.width/2,a.h-c-0,b-this._tile.width,a.h-c-this._tile.height/2,b-this._tile.width/2,a.h-c-this._tile.height],f=new d.polygon(e);return f}}})},{"../core/core.js":7}],37:[function(a,b,c){var d=a("../core/core.js");d.extend({isometric:{_tile:{width:0,height:0},_elements:{},_pos:{x:0,y:0},_z:0,size:function(a,b){return this._tile.width=a,this._tile.height=b>0?b:a/2,this},place:function(a,b,c,e){var f=this.pos2px(a,b);return f.top-=c*(this._tile.height/2),e.attr({x:f.left+d.viewport._x,y:f.top+d.viewport._y}).z+=c,this},pos2px:function(a,b){return{left:a*this._tile.width+(1&b)*(this._tile.width/2),top:b*this._tile.height/2}},px2pos:function(a,b){return{x:-Math.ceil(-a/this._tile.width-.5*(1&b)),y:b/this._tile.height*2}},centerAt:function(a,b){if("number"==typeof a&&"number"==typeof b){var c=this.pos2px(a,b);return d.viewport._x=-c.left+d.viewport.width/2-this._tile.width/2,d.viewport._y=-c.top+d.viewport.height/2-this._tile.height/2,this}return{top:-d.viewport._y+d.viewport.height/2-this._tile.height/2,left:-d.viewport._x+d.viewport.width/2-this._tile.width/2}},area:function(){var a=this.centerAt(),b=this.px2pos(-a.left+d.viewport.width/2,-a.top+d.viewport.height/2),c=this.px2pos(-a.left-d.viewport.width/2,-a.top-d.viewport.height/2);return{x:{start:b.x,end:c.x},y:{start:b.y,end:c.y}}}}})},{"../core/core.js":7}],38:[function(a,b,d){var e=a("../core/core.js"),f=window.document;e.extend({audio:{sounds:{},supported:null,codecs:{ogg:'audio/ogg; codecs="vorbis"',wav:'audio/wav; codecs="1"',webma:'audio/webm; codecs="vorbis"',mp3:'audio/mpeg; codecs="mp3"',m4a:'audio/mp4; codecs="mp4a.40.2"'},volume:1,muted:!1,paused:!1,playCheck:null,_canPlay:function(){if(this.supported={},e.support.audio){var a,b=this.audioElement();for(var c in this.codecs)a=b.canPlayType(this.codecs[c]),""!==a&&"no"!==a?this.supported[c]=!0:this.supported[c]=!1}},supports:function(a){return null===this.supported&&this._canPlay(),this.supported[a]?!0:!1},audioElement:function(){return"undefined"!=typeof Audio?new Audio(""):f.createElement("audio")},create:function(a,b){var c=b.substr(b.lastIndexOf(".")+1).toLowerCase();if(!this.supports(c))return!1;var d=this.audioElement();return d.id=a,d.preload="auto",d.volume=e.audio.volume,d.src=b,e.asset(b,d),this.sounds[a]={obj:d,played:0,volume:e.audio.volume},this.sounds[a]},add:function(a,b){if(e.support.audio){var c,d;if(1===arguments.length&&"object"==typeof a)for(var f in a)for(c in a[f])if(d=e.audio.create(f,a[f][c]))break;if("string"==typeof a&&("string"==typeof b&&(d=e.audio.create(a,b)),"object"==typeof b))for(c in b)if(d=e.audio.create(a,b[c]))break;return d}},play:function(a,b,c){if(0!==b&&e.support.audio&&this.sounds[a]){var d=this.sounds[a],f=this.getOpenChannel();if(!f)return null;f.id=a,f.repeat=b;var g=f.obj;return f.volume=d.volume=d.obj.volume=c||e.audio.volume,g.volume=d.volume,g.src=d.obj.src,this.muted&&(g.volume=0),g.play(),d.played++,f.onEnd=function(){d.played0&&this._cascade(a)}),this.bind("Rotate",function(a){var b=this._cbr||this._mbr||this;this._entry.update(b),this._children.length>0&&this._cascade(a)}),this.bind("Remove",function(){if(this._children){for(var a=0;ai&&i>-1e-10?0:i,j=1e-10>j&&j>-1e-10?0:j;var k=d*i+f*j,l=-d*j+f*i,m=e*i+f*j,n=-e*j+f*i,o=e*i+g*j,p=-e*j+g*i,q=d*i+g*j,r=-d*j+g*i,s=Math.floor(Math.min(k,m,o,q)+a),t=Math.floor(Math.min(l,n,p,r)+b),u=Math.ceil(Math.max(k,m,o,q)+a),v=Math.ceil(Math.max(l,n,p,r)+b);if(this._mbr?(this._mbr._x=s,this._mbr._y=t,this._mbr._w=u-s,this._mbr._h=v-t):this._mbr={_x:s,_y:t,_w:u-s,_h:v-t},this._cbr){var w=this._cbr,x=w.cx,y=w.cy,z=w.r,A=a+(x+this._x-a)*i+(y+this._y-b)*j,B=b-(x+this._x-a)*j+(y+this._y-b)*i;w._x=Math.min(A-z,s),w._y=Math.min(B-z,t),w._w=Math.max(A+z,u)-w._x,w._h=Math.max(B+z,v)-w._y}},_rotate:function(a){var b=this._rotation-a;if(0!==b){this._rotation=a;var c={x:this._origin.x+this._x,y:this._origin.y+this._y};this._calculateMBR();var d=b*h,e=Math.cos(d),f=Math.sin(d);this.trigger("Rotate",{cos:e>-1e-10&&1e-10>e?0:e,sin:f>-1e-10&&1e-10>f?0:f,deg:b,rad:d,o:c})}},area:function(){return this._w*this._h},intersect:function(a,b,c,d){var e,f=this._mbr||this;return e="object"==typeof a?a:{_x:a,_y:b,_w:c,_h:d},f._xe._x&&f._ye._y},within:function(a,b,c,d){var e,f=this._mbr||this;return e="object"==typeof a?a:{_x:a,_y:b,_w:c,_h:d},e._x<=f._x&&e._x+e._w>=f._x+f._w&&e._y<=f._y&&e._y+e._h>=f._y+f._h},contains:function(a,b,c,d){var e,f=this._mbr||this;return e="object"==typeof a?a:{_x:a,_y:b,_w:c,_h:d},e._x>=f._x&&e._x+e._w<=f._x+f._w&&e._y>=f._y&&e._y+e._h<=f._y+f._h},pos:function(a){return a=a||{},a._x=this._x,a._y=this._y,a._w=this._w,a._h=this._h,a},mbr:function(a){return a=a||{},this._mbr?(a._x=this._mbr._x,a._y=this._mbr._y,a._w=this._mbr._w,a._h=this._mbr._h,a):this.pos(a)},isAt:function(a,b){if(this.mapArea)return this.mapArea.containsPoint(a,b);if(this.map)return this.map.containsPoint(a,b);var c=this._mbr||this;return c._x<=a&&c._x+c._w>=a&&c._y<=b&&c._y+c._h>=b},move:function(a,b){return"n"===a.charAt(0)&&(this.y-=b),"s"===a.charAt(0)&&(this.y+=b),("e"===a||"e"===a.charAt(1))&&(this.x+=b),("w"===a||"w"===a.charAt(1))&&(this.x-=b),this},shift:function(a,b,c,d){return a&&(this.x+=a),b&&(this.y+=b),c&&(this.w+=c),d&&(this.h+=d),this},_cascade:function(a){if(a){var b,c=0,d=this._children,e=d.length;if("cos"in a||"sin"in a)for(;e>c;++c)b=d[c],"rotate"in b&&b.rotate(a);else for(var f=this._x-a._x,g=this._y-a._y,h=this._w-a._w,i=this._h-a._h;e>c;++c)b=d[c],b.shift(f,g,h,i)}},attach:function(){for(var a,b=0,c=arguments,d=arguments.length;d>b;++b)a=c[b],a._parent&&a._parent.detach(a),a._parent=this,this._children.push(a);return this},detach:function(a){var b;if(!a){for(b=0;bk;++k)if(h=j[k],i=h._cbr||h._mbr||h,h!==this&&h.__c[a]&&c(i,f)&&(this.canLand=!0,this.trigger("CheckLanding",h),this.canLand)){this._ground=b=h,this.y=h._y-this._h,this.trigger("LandedOnGround",b);break}}}),d.c("GroundAttacher",{_groundAttach:function(a){a.attach(this)},_groundDetach:function(a){a.detach(this)},init:function(){this.requires("Supportable"),this.bind("LandedOnGround",this._groundAttach),this.bind("LiftedOffGround",this._groundDetach)},remove:function(a){this.unbind("LandedOnGround",this._groundAttach),this.unbind("LiftedOffGround",this._groundDetach)}}),d.c("Gravity",{_gravityConst:500,init:function(){this.requires("2D, Supportable, Motion"),this.bind("LiftedOffGround",this._startGravity),this.bind("LandedOnGround",this._stopGravity)},remove:function(a){this.unbind("LiftedOffGround",this._startGravity),this.unbind("LandedOnGround",this._stopGravity)},_gravityCheckLanding:function(a){this._dy<0&&(this.canLand=!1)},gravity:function(a){return this.bind("CheckLanding",this._gravityCheckLanding),this.startGroundDetection(a),this._startGravity(),this},antigravity:function(){return this._stopGravity(),this.stopGroundDetection(),this.unbind("CheckLanding",this._gravityCheckLanding),this},gravityConst:function(a){return this._gravityActive&&(this.ay-=this._gravityConst,this.ay+=a),this._gravityConst=a,this},_startGravity:function(){this._gravityActive=!0,this.ay+=this._gravityConst},_stopGravity:function(){this.ay=0,this.vy=0,this._gravityActive=!1}});var i=function(a,b,c,e){var f=b+c,g="_"+f,h={key:"",oldValue:0};e?d.defineField(a,f,function(){return this[g]},function(a){var b=this[g];a!==b&&(this[g]=a,h.key=f,h.oldValue=b,this.trigger("MotionChange",h))}):d.defineField(a,f,function(){return this[g]},function(a){}),Object.defineProperty(a,g,{value:0,writable:!0,enumerable:!1,configurable:!1})},j=function(a,b,c,e){var f=b+"x",g=b+"y",h="_"+f,i="_"+g;return c?(d.defineField(e,"x",function(){return a[h]},function(b){a[f]=b}),d.defineField(e,"y",function(){return a[i]},function(b){a[g]=b})):(d.defineField(e,"x",function(){return a[h]},function(a){}),d.defineField(e,"y",function(){return a[i]},function(a){})),Object.seal&&Object.seal(e),e};d.c("AngularMotion",{_vrotation:0,_arotation:0,_drotation:0,init:function(){this.requires("2D"),i(this,"v","rotation",!0),i(this,"a","rotation",!0),i(this,"d","rotation",!1),this.__oldRotationDirection=0,this.bind("EnterFrame",this._angularMotionTick)},remove:function(a){this.unbind("EnterFrame",this._angularMotionTick)},resetAngularMotion:function(){return this._drotation=0,this.vrotation=0,this.arotation=0,this},_angularMotionTick:function(a){var b=a.dt/1e3,c=this._rotation,d=this._vrotation,e=this._arotation,f=c+d*b+.5*e*b*b;this.vrotation=d+e*b;var g=this._vrotation,h=g?0>g?-1:1:0;this.__oldRotationDirection!==h&&(this.__oldRotationDirection=h,this.trigger("NewRotationDirection",h)),this._drotation=f-c,0!==this._drotation&&(this.rotation=f,this.trigger("Rotated",c))}}),d.c("Motion",{_vx:0,_vy:0,_ax:0,_ay:0,_dx:0,_dy:0,init:function(){this.requires("2D"),i(this,"v","x",!0),i(this,"v","y",!0),this._velocity=j(this,"v",!0,new d.math.Vector2D),i(this,"a","x",!0),i(this,"a","y",!0),this._acceleration=j(this,"a",!0,new d.math.Vector2D),i(this,"d","x",!1),i(this,"d","y",!1),this._motionDelta=j(this,"d",!1,new d.math.Vector2D),this.__movedEvent={axis:"",oldValue:0},this.__oldDirection={x:0,y:0},this.bind("EnterFrame",this._linearMotionTick)},remove:function(a){this.unbind("EnterFrame",this._linearMotionTick)},resetMotion:function(){return this.vx=0,this.vy=0,this.ax=0,this.ay=0,this._dx=0,this._dy=0,this},motionDelta:function(){return this._motionDelta},velocity:function(){return this._velocity},acceleration:function(){return this._acceleration},_linearMotionTick:function(a){var b=a.dt/1e3,c=this._x,d=this._vx,e=this._ax,f=this._y,g=this._vy,h=this._ay,i=c+d*b+.5*e*b*b,j=f+g*b+.5*h*b*b;this.vx=d+e*b,this.vy=g+h*b;var k=this.__oldDirection,l=this._vx,m=l?0>l?-1:1:0,n=this._vy,o=n?0>n?-1:1:0;(k.x!==m||k.y!==o)&&(k.x=m,k.y=o,this.trigger("NewDirection",k));var p=this.__movedEvent;this._dx=i-c,this._dy=j-f,0!==this._dx&&(this.x=i,p.axis="x",p.oldValue=c,this.trigger("Moved",p)),0!==this._dy&&(this.y=j,p.axis="y",p.oldValue=f,this.trigger("Moved",p))}}),d.polygon=function(a){arguments.length>1&&(a=Array.prototype.slice.call(arguments,0)),this.points=a},d.polygon.prototype={containsPoint:function(a,b){var c,d,e=this.points,f=e.length/2,g=!1;for(c=0,d=f-1;f>c;d=c++)e[2*c+1]>b!=e[2*d+1]>b&&a<(e[2*d]-e[2*c])*(b-e[2*c+1])/(e[2*d+1]-e[2*c+1])+e[2*c]&&(g=!g);return g},shift:function(a,b){for(var c=0,d=this.points,e=d.length;e>c;c+=2)d[c]+=a,d[c+1]+=b},clone:function(){return new d.polygon(this.points.slice(0))},rotate:function(a){for(var b,c,d=0,e=this.points,f=e.length;f>d;d+=2)b=a.o.x+(e[d]-a.o.x)*a.cos+(e[d+1]-a.o.y)*a.sin,c=a.o.y-(e[d]-a.o.x)*a.sin+(e[d+1]-a.o.y)*a.cos,e[d]=b,e[d+1]=c}},d.circle=function(a,b,c){this.x=a,this.y=b,this.radius=c,this.points=[];for(var d,e=0;16>e;e+=2)d=e*Math.PI/8,this.points[e]=this.x+Math.sin(d)*c,this.points[e+1]=this.y+Math.cos(d)*c},d.circle.prototype={containsPoint:function(a,b){var c=this.radius,d=(Math.sqrt,this.x-a),e=this.y-b;return c*c>d*d+e*e},shift:function(a,b){this.x+=a,this.y+=b;for(var c=0,d=this.points,e=d.length;e>c;c+=2)d[c]+=a,d[c+1]+=b},rotate:function(){}},d.matrix=function(a){this.mtx=a,this.width=a[0].length,this.height=a.length},d.matrix.prototype={x:function(a){if(this.width==a.height){for(var b=[],c=0;ca||a>this.mtx.length||1>b||b>this.mtx[0].length?null:this.mtx[a-1][b-1]}}},{"../core/core.js":7,"./spatial-grid.js":43}],40:[function(a,b,c){var d=a("../core/core.js"),e=Math.PI/180;d.c("Collision",{init:function(){this.requires("2D"),this._collisionData={},this.collision()},remove:function(){this._cbr=null,this.unbind("Resize",this._resizeMap),this.unbind("Resize",this._checkBounds)},collision:function(a){if(this.unbind("Resize",this._resizeMap),this.unbind("Resize",this._checkBounds),a){if(arguments.length>1){var b=Array.prototype.slice.call(arguments,0);a=new d.polygon(b)}else a=a.constructor===Array?new d.polygon(a.slice()):a.clone();this._findBounds(a.points)}else a=new d.polygon([0,0,this._w,0,this._w,this._h,0,this._h]),this.bind("Resize",this._resizeMap),this._cbr=null;return this.rotation&&a.rotate({cos:Math.cos(-this.rotation*e),sin:Math.sin(-this.rotation*e),o:{x:this._origin.x,y:this._origin.y}}),this.map=a,this.attach(this.map),this.map.shift(this._x,this._y),this.trigger("NewHitbox",a),this},_findBounds:function(a){for(var b=1/0,c=-(1/0),d=1/0,e=-(1/0),f=a.length,g=0;f>g;g+=2)a[g]c&&(c=a[g]),a[g+1]e&&(e=a[g+1]);var h={cx:(b+c)/2,cy:(d+e)/2,r:Math.sqrt((c-b)*(c-b)+(e-d)*(e-d))/2};return b>=0&&d>=0&&(this._checkBounds=function(){null===this._cbr&&this._w=0&&d>=0&&c<=this._w&&e<=this._h?(this._cbr=null,!1):(this._cbr=h,this._calculateMBR(),!0)},_resizeMap:function(a){var b,c,d=this.rotation*e,f=this.map.points;"w"===a.axis?(d?(b=a.amount*Math.cos(d),c=a.amount*Math.sin(d)):(b=a.amount,c=0),f[2]+=b,f[3]+=c):(d?(c=a.amount*Math.cos(d),b=-a.amount*Math.sin(d)):(b=0,c=a.amount),f[6]+=b,f[7]+=c),f[4]+=b,f[5]+=c},hit:function(a){var b,c,e,f,g=this._cbr||this._mbr||this,h=d.map.search(g,!1),i=0,j=h.length,k={},l=d.rectManager.overlap,m="map"in this&&"containsPoint"in this.map,n=[];if(!j)return!1;for(;j>i;++i)c=h[i],e=c._cbr||c._mbr||c,c&&(b=c[0],!k[b]&&this[0]!==b&&c.__c[a]&&l(e,g)&&(k[b]=c));for(f in k)if(c=k[f],m&&"map"in c){var o=this._SAT(this.map,c.map);o.obj=c,o.type="SAT",o&&n.push(o)}else n.push({obj:c,type:"MBR"});return n.length?n:!1},onHit:function(a,b,c){var d=!1;return this.bind("EnterFrame",function(){var e=this.hit(a);e?(d=!0,b.call(this,e)):d&&("function"==typeof c&&c.call(this),d=!1)}),this},_createCollisionHandler:function(a,b){return function(){var c=this.hit(a);if(b.occurring===!0){if(c!==!1)return;b.occurring=!1,this.trigger("HitOff",a)}else c!==!1&&(b.occurring=!0,this.trigger("HitOn",c))}},checkHits:function(){var a=arguments,b=0;for(1===a.length&&(a=a[0].split(/\s*,\s*/));bl;l++){for(k=l==o-1?0:l+1,q=-(m[2*l+1]-m[2*k+1]),r=m[2*l]-m[2*k],d=Math.sqrt(q*q+r*r),q/=d,r/=d,e=f=1/0,g=h=-(1/0),c=0;o>c;++c)j=m[2*c]*q+m[2*c+1]*r,j>g&&(g=j),e>j&&(e=j);for(c=0;p>c;++c)j=n[2*c]*q+n[2*c+1]*r,j>h&&(h=j),f>j&&(f=j);if(f>e?(i=f-g,q=-q,r=-r):i=e-h,i>=0)return!1;i>s&&(s=i,t=q,u=r)}for(l=0;p>l;l++){for(k=l==p-1?0:l+1,q=-(n[2*l+1]-n[2*k+1]),r=n[2*l]-n[2*k],d=Math.sqrt(q*q+r*r),q/=d,r/=d,e=f=1/0,g=h=-(1/0),c=0;o>c;++c)j=m[2*c]*q+m[2*c+1]*r,j>g&&(g=j),e>j&&(e=j);for(c=0;p>c;++c)j=n[2*c]*q+n[2*c+1]*r,j>h&&(h=j),f>j&&(f=j);if(f>e?(i=f-g,q=-q,r=-r):i=e-h,i>=0)return!1;i>s&&(s=i,t=q,u=r)}return{overlap:s,normal:{x:t,y:u}}}})},{"../core/core.js":7}],41:[function(a,b,c){var d=a("../core/core.js");d.math={abs:function(a){return 0>a?-a:a},amountOf:function(a,b,c){return c>b?(a-b)/(c-b):(a-c)/(b-c)},clamp:function(a,b,c){return a>c?c:b>a?b:a},degToRad:function(a){return a*Math.PI/180},distance:function(a,b,c,e){var f=d.math.squaredDistance(a,b,c,e);return Math.sqrt(parseFloat(f))},lerp:function(a,b,c){return a+(b-a)*c},negate:function(a){return Math.random()=b&&c>=a}},d.math.Vector2D=function(){function a(b,c){if(b instanceof a)this.x=b.x,this.y=b.y;else if(2===arguments.length)this.x=b,this.y=c;else if(arguments.length>0)throw"Unexpected number of arguments for Vector2D()"}return a.prototype.x=0,a.prototype.y=0,a.prototype.add=function(a){return this.x+=a.x,this.y+=a.y,this},a.prototype.angleBetween=function(a){return Math.atan2(this.x*a.y-this.y*a.x,this.x*a.x+this.y*a.y)},a.prototype.angleTo=function(a){return Math.atan2(a.y-this.y,a.x-this.x)},a.prototype.clone=function(){return new a(this)},a.prototype.distance=function(a){return Math.sqrt((a.x-this.x)*(a.x-this.x)+(a.y-this.y)*(a.y-this.y))},a.prototype.distanceSq=function(a){return(a.x-this.x)*(a.x-this.x)+(a.y-this.y)*(a.y-this.y)},a.prototype.divide=function(a){return this.x/=a.x,this.y/=a.y,this},a.prototype.dotProduct=function(a){return this.x*a.x+this.y*a.y},a.prototype.crossProduct=function(a){return this.x*a.y-this.y*a.x},a.prototype.equals=function(b){return b instanceof a&&this.x==b.x&&this.y==b.y},a.prototype.perpendicular=function(b){return b=b||new a,b.setValues(-this.y,this.x)},a.prototype.getNormal=function(b,c){return c=c||new a,c.setValues(b.y-this.y,this.x-b.x).normalize()},a.prototype.isZero=function(){return 0===this.x&&0===this.y},a.prototype.magnitude=function(){return Math.sqrt(this.x*this.x+this.y*this.y)},a.prototype.magnitudeSq=function(){return this.x*this.x+this.y*this.y},a.prototype.multiply=function(a){return this.x*=a.x,this.y*=a.y,this},a.prototype.negate=function(){return this.x=-this.x,this.y=-this.y,this},a.prototype.normalize=function(){var a=Math.sqrt(this.x*this.x+this.y*this.y);return 0===a?(this.x=1,this.y=0):(this.x/=a,this.y/=a),this},a.prototype.scale=function(a,b){return void 0===b&&(b=a),this.x*=a,this.y*=b,this},a.prototype.scaleToMagnitude=function(a){var b=a/this.magnitude();return this.x*=b,this.y*=b,this},a.prototype.setValues=function(b,c){return b instanceof a?(this.x=b.x,this.y=b.y):(this.x=b,this.y=c),this},a.prototype.subtract=function(a){return this.x-=a.x,this.y-=a.y,this},a.prototype.toString=function(){return"Vector2D("+this.x+", "+this.y+")"},a.prototype.translate=function(a,b){return void 0===b&&(b=a),this.x+=a,this.y+=b,this},a.tripleProduct=function(a,b,c,e){e=e||new d.math.Vector2D;var f=a.dotProduct(c),g=b.dotProduct(c);return e.setValues(b.x*f-a.x*g,b.y*f-a.y*g)},a}(),d.math.Matrix2D=function(){return Matrix2D=function(a,b,c,d,e,f){if(a instanceof Matrix2D)this.a=a.a,this.b=a.b,this.c=a.c,this.d=a.d,this.e=a.e,this.f=a.f;else if(6===arguments.length)this.a=a,this.b=b,this.c=c,this.d=d,this.e=e,this.f=f;else if(arguments.length>0)throw"Unexpected number of arguments for Matrix2D()"},Matrix2D.prototype.a=1,Matrix2D.prototype.b=0,Matrix2D.prototype.c=0,Matrix2D.prototype.d=1,Matrix2D.prototype.e=0,Matrix2D.prototype.f=0,Matrix2D.prototype.apply=function(a){var b=a.x;return a.x=b*this.a+a.y*this.c+this.e,a.y=b*this.b+a.y*this.d+this.f,a},Matrix2D.prototype.clone=function(){return new Matrix2D(this)},Matrix2D.prototype.combine=function(a){var b=this.a;return this.a=b*a.a+this.b*a.c,this.b=b*a.b+this.b*a.d,b=this.c,this.c=b*a.a+this.d*a.c,this.d=b*a.b+this.d*a.d,b=this.e,this.e=b*a.a+this.f*a.c+a.e,this.f=b*a.b+this.f*a.d+a.f,this},Matrix2D.prototype.equals=function(a){return a instanceof Matrix2D&&this.a==a.a&&this.b==a.b&&this.c==a.c&&this.d==a.d&&this.e==a.e&&this.f==a.f},Matrix2D.prototype.determinant=function(){return this.a*this.d-this.b*this.c},Matrix2D.prototype.invert=function(){var a=this.determinant();if(0!==a){var b={a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f};this.a=b.d/a,this.b=-b.b/a,this.c=-b.c/a,this.d=b.a/a,this.e=(b.c*b.f-b.e*b.d)/a,this.f=(b.e*b.b-b.a*b.f)/a}return this},Matrix2D.prototype.isIdentity=function(){return 1===this.a&&0===this.b&&0===this.c&&1===this.d&&0===this.e&&0===this.f},Matrix2D.prototype.isInvertible=function(){return 0!==this.determinant()},Matrix2D.prototype.preRotate=function(a){var b=Math.cos(a),c=Math.sin(a),d=this.a;return this.a=b*d-c*this.b,this.b=c*d+b*this.b,d=this.c,this.c=b*d-c*this.d,this.d=c*d+b*this.d,this},Matrix2D.prototype.preScale=function(a,b){return void 0===b&&(b=a),this.a*=a,this.b*=b,this.c*=a,this.d*=b,this},Matrix2D.prototype.preTranslate=function(a,b){return"number"==typeof a?(this.e+=a,this.f+=b):(this.e+=a.x,this.f+=a.y),this},Matrix2D.prototype.rotate=function(a){var b=Math.cos(a),c=Math.sin(a),d=this.a;return this.a=b*d-c*this.b,this.b=c*d+b*this.b,d=this.c,this.c=b*d-c*this.d,this.d=c*d+b*this.d,d=this.e,this.e=b*d-c*this.f,this.f=c*d+b*this.f,this},Matrix2D.prototype.scale=function(a,b){return void 0===b&&(b=a),this.a*=a,this.b*=b,this.c*=a,this.d*=b,this.e*=a,this.f*=b,this},Matrix2D.prototype.setValues=function(a,b,c,d,e,f){return a instanceof Matrix2D?(this.a=a.a,this.b=a.b,this.c=a.c,this.d=a.d,this.e=a.e,this.f=a.f):(this.a=a,this.b=b,this.c=c,this.d=d,this.e=e,this.f=f),this},Matrix2D.prototype.toString=function(){return"Matrix2D(["+this.a+", "+this.c+", "+this.e+"] ["+this.b+", "+this.d+", "+this.f+"] [0, 0, 1])"},Matrix2D.prototype.translate=function(a,b){return"number"==typeof a?(this.e+=this.a*a+this.c*b,this.f+=this.b*a+this.d*b):(this.e+=this.a*a.x+this.c*a.y,this.f+=this.b*a.x+this.d*a.y),this},Matrix2D}()},{"../core/core.js":7}],42:[function(a,b,c){var d=a("../core/core.js");d.extend({rectManager:{merge:function(a,b,c){return"undefined"==typeof c&&(c={}),c._h=Math.max(a._y+a._h,b._y+b._h),c._w=Math.max(a._x+a._w,b._x+b._w),c._x=Math.min(a._x,b._x),c._y=Math.min(a._y,b._y),c._w-=c._x,c._h-=c._y,c},overlap:function(a,b){return a._xb._x&&a._yb._y},mergeSet:function(a){for(var b=0;b0&&b--):b++;return a},boundingRect:function(a){if(a&&a.length){var b,c,d=1,e=a.length,f=a[0];for(f=[f._x,f._y,f._x+f._w,f._y+f._h];e>d;)b=a[d],c=[b._x,b._y,b._x+b._w,b._y+b._h],c[0]f[2]&&(f[2]=c[2]),c[3]>f[3]&&(f[3]=c[3]),d++;return c=f,f={_x:c[0],_y:c[1],_w:c[2]-c[0],_h:c[3]-c[1]}}},_pool:function(){var a=[],b=0;return{get:function(c,d,e,f){a.length<=b&&a.push({});var g=a[b++];return g._x=c,g._y=d,g._w=e,g._h=f,g},copy:function(c){a.length<=b&&a.push({});var d=a[b++];return d._x=c._x,d._y=c._y,d._w=c._w,d._h=c._h,d},recycle:function(a){b--}}}()}})},{"../core/core.js":7}],43:[function(a,b,c){function d(a,b,c){this.keys=a,this.map=c,this.obj=b}var e,f=(a("../core/core.js"),function(a){e=a||64,this.map={}}),g=" ",h={};f.prototype={insert:function(a){var b,c,e=f.key(a),g=new d(e,a,this),h=0;for(h=e.x1;h<=e.x2;h++)for(b=e.y1;b<=e.y2;b++)c=h<<16^b,this.map[c]||(this.map[c]=[]),this.map[c].push(a);return g},search:function(a,b){var c,d,e,g,i,j=f.key(a,h),k=[];for(void 0===b&&(b=!0),c=j.x1;c<=j.x2;c++)for(d=j.y1;d<=j.y2;d++)if(i=this.map[c<<16^d])for(e=0;ec;c++)l=k[c],l&&(m=l[0],l=l._mbr||l,!o[m]&&l._xa._x&&l._ya._y&&(o[m]=k[c]));for(l in o)n.push(o[l]);return n}return k},remove:function(a,b){var c,d,e=0;for(1==arguments.length&&(b=a, 13 | a=f.key(b,h)),e=a.x1;e<=a.x2;e++)for(c=a.y1;c<=a.y2;c++)if(d=e<<16^c,this.map[d]){var g,i=this.map[d],j=i.length;for(g=0;j>g;g++)i[g]&&i[g][0]===b[0]&&i.splice(g,1)}},refresh:function(a){var b,c,d,e,g,h=a.keys,i=a.obj;for(c=h.x1;c<=h.x2;c++)for(d=h.y1;d<=h.y2;d++)if(b=this.map[c<<16^d])for(g=b.length,e=0;g>e;e++)b[e]&&b[e][0]===i[0]&&b.splice(e,1);for(f.key(i,h),c=h.x1;c<=h.x2;c++)for(d=h.y1;d<=h.y2;d++)b=this.map[c<<16^d],b||(b=this.map[c<<16^d]=[]),b.push(i);return a},boundaries:function(){var a,b,c={max:{x:-(1/0),y:-(1/0)},min:{x:1/0,y:1/0}},d={max:{x:-(1/0),y:-(1/0)},min:{x:1/0,y:1/0}};for(var e in this.map)if(this.map[e].length){var f=e>>16,g=e<<16>>16;if(0>g&&(f=-1^f),f>=c.max.x){c.max.x=f;for(a in this.map[e])b=this.map[e][a],"object"==typeof b&&"requires"in b&&(d.max.x=Math.max(d.max.x,b.x+b.w))}if(f<=c.min.x){c.min.x=f;for(a in this.map[e])b=this.map[e][a],"object"==typeof b&&"requires"in b&&(d.min.x=Math.min(d.min.x,b.x))}if(g>=c.max.y){c.max.y=g;for(a in this.map[e])b=this.map[e][a],"object"==typeof b&&"requires"in b&&(d.max.y=Math.max(d.max.y,b.y+b.h))}if(g<=c.min.y){c.min.y=g;for(a in this.map[e])b=this.map[e][a],"object"==typeof b&&"requires"in b&&(d.min.y=Math.min(d.min.y,b.y))}}return d}},f.key=function(a,b){return a._mbr&&(a=a._mbr),b||(b={}),b.x1=Math.floor(a._x/e),b.y1=Math.floor(a._y/e),b.x2=Math.floor((a._w+a._x)/e),b.y2=Math.floor((a._h+a._y)/e),b},f.hash=function(a){return a.x1+g+a.y1+g+a.x2+g+a.y2},d.prototype={update:function(a){f.hash(f.key(a,h))!=f.hash(this.keys)&&this.map.refresh(this)}},b.exports=f},{"../core/core.js":7}]},{},[17]); --------------------------------------------------------------------------------