├── js
├── .gitkeep
└── app.js
├── README.md
├── assets
├── boy.png
├── grass.png
├── item.png
├── step.mp3
├── bgsound.mp3
├── main_bg.png
├── sprites.png
└── success.mp3
├── src
├── config.js
├── index.js
├── game.js
├── solver.js
└── data.js
├── .eslintrc.js
├── .babelrc
├── index.html
├── .gitignore
├── webpack.config.js
├── package.json
└── css
└── style.css
/js/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Boxbox
2 |
3 | https://akira-cn.github.io/boxbox/
4 |
--------------------------------------------------------------------------------
/assets/boy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/boy.png
--------------------------------------------------------------------------------
/assets/grass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/grass.png
--------------------------------------------------------------------------------
/assets/item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/item.png
--------------------------------------------------------------------------------
/assets/step.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/step.mp3
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const BOUND_X = 15;
4 | export const BOUND_Y = 10;
--------------------------------------------------------------------------------
/assets/bgsound.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/bgsound.mp3
--------------------------------------------------------------------------------
/assets/main_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/main_bg.png
--------------------------------------------------------------------------------
/assets/sprites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/sprites.png
--------------------------------------------------------------------------------
/assets/success.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira-cn/boxbox/HEAD/assets/success.mp3
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | globals: {
3 | },
4 | extends: "eslint-config-sprite",
5 | plugins: ['html'],
6 | rules: {
7 | "complexity": ["warn", 25],
8 | 'import/prefer-default-export': 'off',
9 | },
10 | }
11 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "presets": [
4 | ["@babel/preset-env",
5 | {
6 | "targets": {
7 | "browsers": [
8 | "> 1%",
9 | "last 2 versions",
10 | "not ie <= 8"
11 | ]
12 | }
13 | }
14 | ]
15 | ],
16 | "plugins": [
17 | "@babel/plugin-proposal-class-properties",
18 | [
19 | "@babel/plugin-transform-runtime",
20 | {
21 | "corejs": false,
22 | "helpers": true,
23 | "regenerator": true,
24 | "useESModules": false
25 | }
26 | ]
27 | ]
28 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 推箱子
8 |
9 |
10 |
11 | 选择关卡后,使用键盘 上、下、左、右 键控制
12 |
13 |
14 |
15 |
16 | 第 关
17 |
18 |
19 |
你赢了!
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Logs
3 | logs
4 | *.log
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage/
16 | .nyc_output/
17 |
18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19 | .grunt
20 |
21 | # node-waf configuration
22 | .lock-wscript
23 |
24 | # Dependency directory
25 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
26 | node_modules/
27 |
28 | # IDE config
29 | .idea
30 |
31 | # output
32 | output/
33 | output.tar.gz
34 |
35 | app/
36 |
37 | runtime/
38 |
39 | frames/
40 | ffmpeg.sh
41 |
42 | .DS_Store
43 |
44 | sftp-config.json
45 | package-lock.json
46 |
47 | .vscode
48 | jsconfig.json
49 | esconfig.json
50 |
51 | temp/*.js
52 | .jedi-tests
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = function (env = {}) {
4 | return {
5 | mode: env.production ? 'production' : 'development',
6 | entry: './src/index',
7 | output: {
8 | path: path.resolve(__dirname, 'js'),
9 | filename: 'app.js',
10 | publicPath: '/js/',
11 | library: ['Boxman'],
12 | libraryTarget: 'umd',
13 | },
14 |
15 | module: {
16 | rules: [
17 | {
18 | test: /\.js$/,
19 | exclude: /(node_modules|bower_components)/,
20 | use: {
21 | loader: 'babel-loader',
22 | },
23 | },
24 | ],
25 |
26 | /* Advanced module configuration (click to show) */
27 | },
28 |
29 | // externals: {
30 | // spritejs: 'spritejs',
31 | // },
32 | // Don't follow/bundle these modules, but request them at runtime from the environment
33 |
34 | stats: 'errors-only',
35 | // lets you precisely control what bundle information gets displayed
36 |
37 | devServer: {
38 | contentBase: path.join(__dirname, '.'),
39 | compress: true,
40 | port: 9090,
41 | // ...
42 | },
43 |
44 | plugins: [
45 | // ...
46 | ],
47 | // list of additional plugins
48 |
49 |
50 | /* Advanced configuration (click to show) */
51 | };
52 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "2019-contest",
3 | "version": "1.0.0",
4 | "description": "这是星计划校招选拔的综合挑战题",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --watch-poll",
8 | "build": "webpack --env.production",
9 | "lint": "eslint src --fix",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/75camp/2019-contest.git"
15 | },
16 | "keywords": [],
17 | "author": "",
18 | "license": "ISC",
19 | "bugs": {
20 | "url": "https://github.com/75camp/2019-contest/issues"
21 | },
22 | "homepage": "https://github.com/75camp/2019-contest#readme",
23 | "devDependencies": {
24 | "@babel/cli": "^7.2.3",
25 | "@babel/core": "^7.4.0",
26 | "@babel/plugin-proposal-class-properties": "^7.4.0",
27 | "@babel/plugin-transform-runtime": "^7.4.0",
28 | "@babel/preset-env": "^7.4.2",
29 | "babel-eslint": "^10.0.1",
30 | "babel-loader": "^8.0.5",
31 | "eslint": "^5.15.3",
32 | "eslint-config-sprite": "^1.0.6",
33 | "eslint-plugin-html": "^5.0.3",
34 | "webpack": "^4.29.6",
35 | "webpack-cli": "^3.3.0",
36 | "webpack-dev-server": "^3.2.1"
37 | },
38 | "dependencies": {
39 | "@babel/runtime": "^7.4.2",
40 | "greenlet": "^1.0.1",
41 | "howler": "^2.1.1"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | width: 100%;
3 | height: 100%;
4 | margin: 0;
5 | padding: 0;
6 | }
7 |
8 | body {
9 | display: flex;
10 | }
11 |
12 | #info {
13 | position: absolute;
14 | padding: 20px;
15 | }
16 |
17 | .gamepanel {
18 | margin: auto;
19 | }
20 |
21 | .levelpanel {
22 | text-align: right;
23 | font-size: 14px;
24 | margin-bottom: 3px;
25 | }
26 |
27 | #currentlevel {
28 | width: 26px;
29 | text-align: center;
30 | }
31 |
32 | #boxmap {
33 | position: relative;
34 | overflow: hidden;
35 | width: 480px;
36 | height: 320px;
37 | background-image: url(../assets/grass.png);
38 | }
39 |
40 | #boxmap > i {
41 | display: inline-block;
42 | position: absolute;
43 | width: 32px;
44 | height: 32px;
45 | background-image: url(../assets/sprites.png);
46 | background-repeat: no-repeat;
47 | }
48 |
49 | #game-result {
50 | position: absolute;
51 | left: 50%;
52 | top: 88%;
53 | transform: translate(-50%, -50%);
54 | color: #fff;
55 | z-index: 999;
56 | font-size: 4rem;
57 | font-weight: bold;
58 | opacity: 0;
59 | transition: all .3s;
60 | }
61 |
62 | #game-result.show {
63 | top: 38%;
64 | opacity: 1;
65 | transition: all .6s ease-out;
66 | }
67 |
68 | @keyframes walk {
69 | 0% {background-position-y: -96px}
70 | 33% {background-position-y: -32px}
71 | 66% {background-position-y: -64px}
72 | 100% {background-position-y: -96px}
73 | }
74 |
75 | .tree {
76 | background-position: -96px 0;
77 | }
78 |
79 | .spot {
80 | background-position: 0 0;
81 | }
82 |
83 | .bucket {
84 | background-position: -32px 0;
85 | z-index: 1;
86 | }
87 |
88 | .boxman {
89 | background-position-y: -96px;
90 | z-index: 2;
91 | }
92 |
93 | .up {
94 | background-position-x: 0px;
95 | }
96 | .right {
97 | background-position-x: -32px;
98 | }
99 | .down {
100 | background-position-x: -64px;
101 | }
102 | .left {
103 | background-position-x: -96px;
104 | }
105 |
106 | .walk {
107 | animation: walk step-end .2s forwards;
108 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import {Howl} from 'howler';
2 | import BoxGame from './game';
3 |
4 | function wait(ms) {
5 | return new Promise((resolve) => {
6 | setTimeout(resolve, ms);
7 | });
8 | }
9 |
10 | const bgSound = new Howl({
11 | src: ['assets/bgsound.mp3'],
12 | loop: true,
13 | });
14 |
15 | bgSound.play();
16 |
17 | const stepSound = new Howl({
18 | src: ['assets/step.mp3'],
19 | });
20 |
21 | const spotSound = new Howl({
22 | src: ['assets/success.mp3'],
23 | });
24 |
25 | const currentLevel = document.getElementById('currentlevel');
26 | const previousLevel = document.getElementById('previouslevel');
27 | const nextLevel = document.getElementById('nextlevel');
28 | const reset = document.getElementById('reset');
29 | const autoPlay = document.getElementById('autoplay');
30 |
31 | const playLevel = Number(localStorage.getItem('playlevel')) || 1;
32 |
33 | const app = new BoxGame({
34 | container: document.getElementById('boxmap'),
35 | onload(level) {
36 | currentLevel.value = level;
37 | },
38 | onmove([man, bucket], direction) {
39 | let sound = stepSound;
40 | if(bucket) {
41 | let [x, y] = this.getXY(bucket);
42 | if(direction === 'left') {
43 | x--;
44 | } else if(direction === 'right') {
45 | x++;
46 | } else if(direction === 'up') {
47 | y--;
48 | } else {
49 | y++;
50 | }
51 | if(this.getSpot(x, y)) {
52 | sound = spotSound;
53 | }
54 | }
55 | sound.play();
56 | },
57 | async onLevelComplete(level) {
58 | localStorage.setItem('playlevel', level + 1);
59 | const result = document.getElementById('game-result');
60 | result.className = 'show';
61 | await wait(1300);
62 | result.className = '';
63 | await wait(200);
64 | this.load(level + 1);
65 | },
66 | });
67 |
68 | app.load(playLevel);
69 |
70 | currentLevel.addEventListener('change', ({target}) => {
71 | app.load(Number(target.value));
72 | });
73 |
74 | previousLevel.addEventListener('click', () => {
75 | app.load(app.level - 1);
76 | });
77 |
78 | nextLevel.addEventListener('click', () => {
79 | app.load(app.level + 1);
80 | });
81 |
82 | reset.addEventListener('click', () => {
83 | app.load(app.level);
84 | });
85 |
86 | autoPlay.addEventListener('click', async () => {
87 | autoPlay.disabled = true;
88 | autoPlay.innerHTML = '思考中...';
89 | const steps = await app.solve(app.level);
90 | autoPlay.innerHTML = '行动中...';
91 | await app.autoPlay(steps, app.level);
92 | autoPlay.disabled = false;
93 | autoPlay.innerHTML = '自动过关';
94 | });
95 |
96 | // for debug
97 | window.app = app;
98 |
--------------------------------------------------------------------------------
/src/game.js:
--------------------------------------------------------------------------------
1 | import getData from './data';
2 | import {BOUND_X, BOUND_Y} from './config';
3 | import solver from './solver';
4 |
5 | const _level = Symbol('level');
6 |
7 | export default class BoxGame {
8 | static ITEM_WIDTH = 32;
9 |
10 | static MAX_LEVEL = 113;
11 |
12 | constructor({container, onload, onmove, onLevelComplete}) {
13 | this.container = container;
14 | this.onload = onload;
15 | this.onmove = onmove;
16 | this.onLevelComplete = onLevelComplete;
17 | }
18 |
19 | moveTo(item, x, y) {
20 | item.dataset.x = x;
21 | item.dataset.y = y;
22 | item.style.left = `${x * BoxGame.ITEM_WIDTH}px`;
23 | item.style.top = `${y * BoxGame.ITEM_WIDTH}px`;
24 | }
25 |
26 | addItem(type, x, y) {
27 | const item = document.createElement('i');
28 | item.className = type;
29 |
30 | if(type === 'boxman') {
31 | item.className += ' down';
32 | }
33 |
34 | this.moveTo(item, x, y);
35 | this.container.appendChild(item);
36 | }
37 |
38 | get boxman() {
39 | return this.container.querySelector('.boxman');
40 | }
41 |
42 | getXY(item) {
43 | return [Number(item.dataset.x), Number(item.dataset.y)];
44 | }
45 |
46 | getItem(x, y) {
47 | const items = this.container.children;
48 | for(let i = 0; i < items.length; i++) {
49 | const item = items[i];
50 | if(x === Number(item.dataset.x) && y === Number(item.dataset.y) && item.className !== 'spot') {
51 | return item;
52 | }
53 | }
54 | return null;
55 | }
56 |
57 | getSpot(x, y) {
58 | const items = this.container.querySelectorAll('.spot');
59 | for(let i = 0; i < items.length; i++) {
60 | const item = items[i];
61 | if(x === Number(item.dataset.x) && y === Number(item.dataset.y)) {
62 | return item;
63 | }
64 | }
65 | return null;
66 | }
67 |
68 | isOutOfBound(x, y) {
69 | return x < 0 || y < 0 || x >= BOUND_X || y >= BOUND_Y;
70 | }
71 |
72 | isEmpty(x, y) {
73 | return !this.isOutOfBound(x, y) && !this.getItem(x, y);
74 | }
75 |
76 | isAtSpot(bucket) {
77 | const spots = this.container.querySelectorAll('.spot');
78 | for(let i = 0; i < spots.length; i++) {
79 | const spot = spots[i];
80 | if(bucket.dataset.x === spot.dataset.x && bucket.dataset.y === spot.dataset.y) {
81 | return true;
82 | }
83 | }
84 | return false;
85 | }
86 |
87 | async move(direction = 'right') {
88 | const boxman = this.boxman;
89 | const x = Number(boxman.dataset.x),
90 | y = Number(boxman.dataset.y);
91 |
92 | let item = null;
93 |
94 | if(direction === 'left') {
95 | item = this.getItem(x - 1, y);
96 | } else if(direction === 'right') {
97 | item = this.getItem(x + 1, y);
98 | } else if(direction === 'up') {
99 | item = this.getItem(x, y - 1);
100 | } else if(direction === 'down') {
101 | item = this.getItem(x, y + 1);
102 | }
103 |
104 | if(!item) {
105 | if(this.onmove) this.onmove([boxman], direction);
106 | boxman.className = `boxman ${direction} walk`;
107 | await this.moveItem(boxman, direction);
108 | boxman.className = `boxman ${direction}`;
109 | } else if(item.className === 'bucket'
110 | && (direction === 'left' && this.isEmpty(x - 2, y)
111 | || direction === 'right' && this.isEmpty(x + 2, y)
112 | || direction === 'up' && this.isEmpty(x, y - 2)
113 | || direction === 'down' && this.isEmpty(x, y + 2))) {
114 | if(this.onmove) this.onmove([boxman, item], direction);
115 | boxman.className = `boxman ${direction} walk`;
116 | await Promise.all([
117 | this.moveItem(boxman, direction),
118 | this.moveItem(item, direction),
119 | ]);
120 | boxman.className = `boxman ${direction}`;
121 | } else {
122 | boxman.className = `boxman ${direction}`;
123 | }
124 | }
125 |
126 | moveItem(item, direction = 'right') {
127 | let from,
128 | to,
129 | prop;
130 | if(direction === 'left' || direction === 'right') {
131 | from = Number(item.dataset.x);
132 | to = direction === 'left' ? from - 1 : from + 1;
133 | prop = 'left';
134 | } else {
135 | from = Number(item.dataset.y);
136 | to = direction === 'up' ? from - 1 : from + 1;
137 | prop = 'top';
138 | }
139 |
140 | return new Promise((resolve) => {
141 | const startTime = Date.now();
142 | const that = this;
143 | requestAnimationFrame(function update() {
144 | const p = Math.min(1.0, (Date.now() - startTime) / 200);
145 | item.style[prop] = `${BoxGame.ITEM_WIDTH * ((1 - p) * from + p * to)}px`;
146 | if(p < 1.0) {
147 | requestAnimationFrame(update);
148 | } else {
149 | if(prop === 'left') that.moveTo(item, to, item.dataset.y);
150 | else that.moveTo(item, item.dataset.x, to);
151 | resolve();
152 | }
153 | });
154 | });
155 | }
156 |
157 | isWin() {
158 | // 检查是否箱子都在spot中
159 | const buckets = this.container.querySelectorAll('.bucket');
160 | return Array.from(buckets).every(bucket => this.isAtSpot(bucket));
161 | }
162 |
163 | waitCommand() {
164 | return new Promise((resolve) => {
165 | if(this._command) window.removeEventListener('keydown', this._command);
166 | this._command = (event) => {
167 | const keyCode = event.keyCode;
168 | switch (keyCode) {
169 | case 37:
170 | resolve('left');
171 | break;
172 | case 38:
173 | resolve('up');
174 | break;
175 | case 39:
176 | resolve('right');
177 | break;
178 | case 40:
179 | resolve('down');
180 | break;
181 | default:
182 | resolve(null);
183 | break;
184 | }
185 | };
186 | window.addEventListener('keydown', this._command, {once: true});
187 | });
188 | }
189 |
190 | clear() {
191 | this.container.innerHTML = '';
192 | }
193 |
194 | async solve(level = this.level) {
195 | const key = `solved${level}`;
196 | const steps = localStorage.getItem(key);
197 | if(steps) {
198 | return steps.split(',');
199 | }
200 |
201 | const result = await solver(getData(level));
202 | localStorage.setItem(key, result.join());
203 | return result;
204 | }
205 |
206 | get level() {
207 | return this[_level];
208 | }
209 |
210 | init(level = this.level) {
211 | const {trees, spots, buckets, man} = getData(level);
212 | this.clear();
213 | trees.forEach(([x, y]) => this.addItem('tree', x, y));
214 | spots.forEach(([x, y]) => this.addItem('spot', x, y));
215 | buckets.forEach(([x, y]) => this.addItem('bucket', x, y));
216 | this.addItem('boxman', ...man);
217 | }
218 |
219 | async autoPlay(steps, level = this.level) {
220 | this.init(level);
221 | /* eslint-disable no-await-in-loop */
222 | for(let i = 0; i < steps.length; i++) {
223 | const direction = steps[i];
224 | await this.move(direction);
225 | }
226 | /* eslint-enable no-await-in-loop */
227 | if(this.onLevelComplete && this.isWin()) {
228 | await this.onLevelComplete(level);
229 | }
230 | }
231 |
232 | async load(level) {
233 | if(level <= 0) level = BoxGame.MAX_LEVEL;
234 | else if(Number.isNaN(level) || level > BoxGame.MAX_LEVEL) level = 1;
235 | this[_level] = level;
236 |
237 | this.init(level);
238 | if(this.onload) {
239 | this.onload(level);
240 | }
241 | /* eslint-disable no-await-in-loop */
242 | do {
243 | const direction = await this.waitCommand();
244 | if(direction) {
245 | await this.move(direction);
246 | }
247 | } while(!this.isWin());
248 | /* eslint-enable no-await-in-loop */
249 |
250 | if(this.onLevelComplete) {
251 | await this.onLevelComplete(level);
252 | }
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/src/solver.js:
--------------------------------------------------------------------------------
1 | import greenlet from 'greenlet';
2 |
3 | export default greenlet((data) => {
4 | const TREE = 1,
5 | EMPTY = 0;
6 |
7 | const BOUND_X = 15;
8 | const BOUND_Y = 10;
9 |
10 | const map = Array((BOUND_X + 1) * (BOUND_Y + 1)).fill(0);
11 |
12 | data.trees.forEach((t) => {
13 | map[t[1] * BOUND_X + t[0]] = TREE;
14 | });
15 |
16 | const allBuckets = new Set(data.buckets.map(b => b[1] * BOUND_X + b[0]));
17 | const spots = data.spots.map(s => s[1] * BOUND_X + s[0]);
18 |
19 | function isEmpty(buckets, idx) {
20 | return map[idx] === EMPTY && !buckets.has(idx);
21 | }
22 |
23 | function isBucketInSpot(idx) {
24 | return spots.some(spot => spot === idx);
25 | }
26 |
27 | function deadBucket(buckets, bucket) {
28 | const fixed = new Set();
29 |
30 | function isImmovable(idx) {
31 | return map[idx] === TREE || map[idx] == null
32 | || buckets.has(idx) && !canMove(idx);
33 | }
34 |
35 | function canMove(idx) {
36 | if(fixed.has(idx)) return false;
37 | fixed.add(idx);
38 |
39 | const left = idx % BOUND_X > 0 && isImmovable(idx - 1),
40 | right = idx % BOUND_X < BOUND_X - 1 && isImmovable(idx + 1),
41 | top = isImmovable(idx - BOUND_X),
42 | down = isImmovable(idx + BOUND_X);
43 |
44 | if((left && top)
45 | || (top && right)
46 | || (right && down)
47 | || (down && left)) {
48 | return false;
49 | }
50 | fixed.delete(idx);
51 | return true;
52 | }
53 |
54 | const movable = canMove(bucket);
55 | if(movable) return false;
56 | if(isBucketInSpot(bucket)) {
57 | return Array.from(fixed).some(bucket => !isBucketInSpot(bucket));
58 | }
59 | return true;
60 | }
61 |
62 | const MOVE_MAN = 1,
63 | MOVE_BOX = 2;
64 |
65 | function testMove(buckets, nextnext, next) {
66 | buckets.delete(next);
67 | buckets.add(nextnext);
68 | if(deadBucket(buckets, nextnext)) {
69 | buckets.delete(nextnext);
70 | buckets.add(next);
71 | return 0;
72 | }
73 | return MOVE_BOX;
74 | }
75 |
76 | function makeDirectionXY(direction, delta = 1) {
77 | const getXYs = [
78 | (x, y) => [x - delta, y],
79 | (x, y) => [x + delta, y],
80 | (x, y) => [x, y - delta],
81 | (x, y) => [x, y + delta],
82 | ];
83 | return getXYs[direction];
84 | }
85 |
86 | function getPos(x, y, direction) {
87 | if(x < 0 || x >= BOUND_X) return null;
88 | if(y < 0 || y >= BOUND_Y) return null;
89 | return y * BOUND_X + x;
90 | }
91 |
92 | function makeMove(direction) {
93 | const getNextXY = makeDirectionXY(direction);
94 | const getNextNextXY = makeDirectionXY(direction, 2);
95 | return (buckets, x, y) => {
96 | let pos = getNextXY(x, y);
97 | const next = getPos(pos[0], pos[1]);
98 | if(next && isEmpty(buckets, next)) {
99 | return MOVE_MAN;
100 | }
101 | if(next && buckets.has(next)) {
102 | pos = getNextNextXY(x, y);
103 | const nextnext = getPos(pos[0], pos[1]);
104 | if(nextnext && isEmpty(buckets, nextnext)) {
105 | return testMove(buckets, nextnext, next);
106 | }
107 | }
108 | return 0;
109 | };
110 | }
111 |
112 | function checkSpots(buckets) {
113 | return spots.every((s) => {
114 | return buckets.has(s);
115 | });
116 | }
117 |
118 | const LEFT = 0,
119 | RIGHT = 1,
120 | UP = 2,
121 | DOWN = 3;
122 |
123 | let results = null;
124 | const x = Number(data.man[0]),
125 | y = Number(data.man[1]);
126 |
127 | const recordSet = {};
128 | function getRecord(b1, b2) {
129 | if(recordSet[b1] == null) return null;
130 | return recordSet[b1][b2];
131 | }
132 |
133 | function setRecord(b1, b2, pos) {
134 | const poss = getRecord(b1, b2) || [0, 0, 0, 0, 0];
135 | setPos(poss, pos);
136 | recordSet[b1] = recordSet[b1] || {};
137 | recordSet[b1][b2] = poss;
138 | }
139 |
140 | function hasPos(poss, pos) {
141 | let idx = 0;
142 | while(pos >= 30) {
143 | pos -= 30;
144 | idx++;
145 | }
146 | return poss[idx] & (1 << pos);
147 | }
148 |
149 | function setPos(poss, pos) {
150 | let idx = 0;
151 | while(pos >= 30) {
152 | pos -= 30;
153 | idx++;
154 | }
155 | poss[idx] |= (1 << pos);
156 | }
157 |
158 | function pack({buckets, x, y, step, pre}) {
159 | const arr = new Uint32Array(4);
160 | buckets = Array.from(buckets).sort();
161 | for(let i = 0; i < 8; i++) {
162 | let bucket = buckets[i];
163 | if(bucket == null) bucket = 0xff;
164 | if(i < 4) {
165 | arr[0] |= bucket << (8 * i);
166 | } else {
167 | arr[1] |= bucket << (8 * (i - 4));
168 | }
169 | }
170 | arr[2] |= x;
171 | arr[2] |= y << 8;
172 | if(pre !== 0xffffffff) {
173 | arr[2] |= step << 16;
174 | }
175 | arr[3] = pre;
176 | return arr;
177 | }
178 |
179 | function unpack(a, b, c, d) {
180 | let buckets = [
181 | a & 0xff,
182 | (a >>> 8) & 0xff,
183 | (a >>> 16) & 0xff,
184 | (a >>> 24) & 0xff,
185 | b & 0xff,
186 | (b >>> 8) & 0xff,
187 | (b >>> 16) & 0xff,
188 | (b >>> 24) & 0xff,
189 | ];
190 | buckets = new Set(buckets.filter(b => b !== 0xff));
191 | const x = c & 0xff;
192 | const y = (c >> 8) & 0xff;
193 | let step = -1;
194 | if(d !== 0xffffffff) {
195 | step = (c >> 16) & 0xff;
196 | }
197 | return {buckets, x, y, step, pre: d};
198 | }
199 |
200 | // 以两位Uint32来表示所有的8个buckets,以一位Uint32来表示x,y,direction,以一位Uint32来表示preIndex
201 | const list = new Uint32Array(256 * 1024 * 1024);
202 | const packed = pack({buckets: allBuckets, pre: -1, x, y});
203 | list[0] = packed[0];
204 | list[1] = packed[1];
205 | list[2] = packed[2];
206 | list[3] = packed[3];
207 |
208 | setRecord(list[0], list[1], getPos(x, y));
209 |
210 | function getSteps(idx) {
211 | const data = unpack(list[idx], list[idx + 1], list[idx + 2], list[idx + 3]);
212 | if(data.step >= 0) {
213 | return getSteps(data.pre).concat(data.step);
214 | }
215 | return [];
216 | }
217 |
218 | let count = 4;
219 |
220 | function bfs(buckets, i, x, y, direction) {
221 | const move = makeMove(direction);
222 | const getPosByXY = makeDirectionXY(direction);
223 |
224 | const mvb = new Set(buckets);
225 | const check = move(mvb, x, y);
226 | if(check) {
227 | const pos = getPosByXY(x, y);
228 | if(check === MOVE_BOX && checkSpots(mvb)) {
229 | results = getSteps(i).concat(direction);
230 | return true;
231 | }
232 | const packed = pack({buckets: mvb, pre: i, step: direction, x: pos[0], y: pos[1]});
233 | const poss = getRecord(packed[0], packed[1]);
234 | if(!poss) {
235 | list[count] = packed[0];
236 | list[count + 1] = packed[1];
237 | list[count + 2] = packed[2];
238 | list[count + 3] = packed[3];
239 | count += 4;
240 | setRecord(packed[0], packed[1], getPos(pos[0], pos[1]));
241 | } else {
242 | const idx = getPos(pos[0], pos[1]);
243 | if(!hasPos(poss, idx)) {
244 | list[count] = packed[0];
245 | list[count + 1] = packed[1];
246 | list[count + 2] = packed[2];
247 | list[count + 3] = packed[3];
248 | count += 4;
249 | setPos(poss, idx);
250 | }
251 | }
252 | }
253 | return false;
254 | }
255 |
256 | for(let i = 0; i < list.length; i += 4) {
257 | if(list[i] === 0) {
258 | break;
259 | }
260 | const {buckets, x, y} = unpack(list[i], list[i + 1], list[i + 2], list[i + 3]);
261 | if(bfs(buckets, i, x, y, LEFT)
262 | || bfs(buckets, i, x, y, RIGHT)
263 | || bfs(buckets, i, x, y, UP)
264 | || bfs(buckets, i, x, y, DOWN)) break;
265 | }
266 |
267 | const m = ['left', 'right', 'up', 'down'];
268 | return results.map(r => m[r]);
269 | });
270 |
--------------------------------------------------------------------------------
/src/data.js:
--------------------------------------------------------------------------------
1 | const gameData = [{tree: '4,7|5,7|6,7|7,7|8,7|9,7|10,7|4,6|10,6|4,5|10,5|4,4|10,4|4,3|5,3|6,3|7,3|8,3|9,3|10,3', box: '8,6|6,5|8,5|6,4', goal: '5,6|9,6|5,4|9,4', boy: '7,5'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|9,2|10,2|3,3|7,3|10,3|3,4|10,4|3,5|7,5|10,5|3,6|4,6|5,6|6,6|7,6|8,6|9,6|10,6', box: '7,4', goal: '9,4', boy: '8,4'}, {tree: '6,2|7,2|8,2|9,2|4,3|5,3|6,3|9,3|4,4|9,4|10,4|4,5|10,5|4,6|6,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '6,4|6,5', goal: '8,4|7,6', boy: '5,6'}, {tree: '5,1|6,1|7,1|8,1|9,1|10,1|4,2|5,2|10,2|4,3|8,3|10,3|4,4|10,4|4,5|7,5|9,5|10,5|4,6|5,6|9,6|5,7|6,7|7,7|8,7|9,7', box: '6,3|7,4|8,5', goal: '8,2|6,3|6,4', boy: '7,6'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|4,3|6,3|8,3|10,3|4,4|10,4|4,5|9,5|10,5|4,6|7,6|8,6|9,6|4,7|5,7|6,7|7,7', box: '8,4|6,5|7,5', goal: '7,2|7,3|5,5', boy: '8,2'}, {tree: '7,1|8,1|9,1|10,1|4,2|5,2|6,2|7,2|10,2|4,3|10,3|4,4|10,4|4,5|5,5|8,5|9,5|10,5|5,6|8,6|5,7|8,7|5,8|6,8|7,8|8,8', box: '7,3|8,3|6,6', goal: '7,3|7,5|7,7', boy: '9,2'}, {tree: '4,1|5,1|6,1|8,1|9,1|10,1|4,2|6,2|7,2|8,2|10,2|4,3|6,3|10,3|4,4|10,4|4,5|10,5|4,6|7,6|10,6|4,7|7,7|8,7|9,7|10,7|4,8|5,8|6,8|7,8', box: '6,4|7,4|7,5', goal: '5,2|9,2|9,3', boy: '9,4'}, {tree: '6,1|7,1|8,1|9,1|6,2|9,2|10,2|3,3|4,3|5,3|6,3|10,3|3,4|6,4|10,4|3,5|9,5|10,5|3,6|8,6|9,6|3,7|4,7|8,7|4,8|5,8|6,8|7,8|8,8', box: '7,4|8,4|7,6', goal: '4,4|4,6|5,7', boy: '8,2'}, {tree: '3,2|4,2|5,2|6,2|7,2|3,3|7,3|8,3|9,3|10,3|3,4|10,4|3,5|6,5|8,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '5,4|7,5|8,6', goal: '5,3|6,3|7,6', boy: '5,6'}, {tree: '6,1|7,1|8,1|9,1|10,1|4,2|5,2|6,2|10,2|4,3|8,3|10,3|4,4|10,4|4,5|7,5|10,5|4,6|9,6|10,6|4,7|8,7|9,7|4,8|5,8|6,8|7,8|8,8', box: '6,3|6,4|7,4', goal: '9,2|6,4|6,5', boy: '8,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|3,2|9,2|3,3|7,3|9,3|10,3|3,4|5,4|10,4|3,5|8,5|10,5|3,6|4,6|5,6|6,6|10,6|6,7|7,7|8,7|9,7|10,7', box: '6,3|7,4|7,5', goal: '4,2|8,2|8,4', boy: '7,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|9,2|10,2|4,3|6,3|10,3|4,4|10,4|4,5|7,5|10,5|4,6|5,6|9,6|10,6|5,7|6,7|7,7|8,7|9,7', box: '7,3|8,3|6,5', goal: '5,2|7,2|5,3', boy: '8,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|9,2|10,2|4,3|6,3|10,3|4,4|8,4|10,4|4,5|10,5|4,6|5,6|8,6|9,6|10,6|5,7|8,7|5,8|6,8|7,8|8,8', box: '6,5|7,5|8,5', goal: '5,2|6,4|7,5', boy: '6,6'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|10,2|3,3|5,3|7,3|10,3|3,4|10,4|3,5|4,5|5,5|6,5|7,5|10,5|7,6|10,6|7,7|8,7|9,7|10,7', box: '5,4|8,4|9,5', goal: '4,2|8,2|9,4', boy: '4,4'}, {tree: '3,1|4,1|5,1|6,1|3,2|6,2|3,3|6,3|7,3|8,3|9,3|10,3|3,4|10,4|3,5|4,5|10,5|4,6|6,6|8,6|9,6|10,6|4,7|8,7|4,8|5,8|6,8|7,8|8,8', box: '6,4|5,5|7,6', goal: '5,4|6,4|5,7', boy: '7,7'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|9,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|4,5|6,5|8,5|9,5|10,5|4,6|8,6|4,7|5,7|6,7|7,7|8,7', box: '6,4|8,4|5,5', goal: '6,3|4,4|7,4', boy: '6,2'}, {tree: '5,1|6,1|7,1|8,1|9,1|4,2|5,2|9,2|4,3|7,3|9,3|4,4|9,4|10,4|4,5|10,5|4,6|5,6|7,6|10,6|5,7|9,7|10,7|5,8|6,8|7,8|8,8|9,8', box: '6,3|6,5|8,6', goal: '6,4|6,5|6,7', boy: '8,4'}, {tree: '4,1|5,1|6,1|7,1|3,2|4,2|7,2|8,2|9,2|10,2|3,3|10,3|3,4|5,4|10,4|3,5|7,5|10,5|3,6|4,6|5,6|6,6|7,6|10,6|7,7|8,7|9,7|10,7', box: '6,3|6,4|8,4', goal: '4,3|5,3|9,3', boy: '4,5'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|10,2|4,3|10,3|4,4|5,4|6,4|8,4|10,4|3,5|4,5|10,5|3,6|9,6|10,6|3,7|7,7|8,7|9,7|3,8|4,8|5,8|6,8|7,8', box: '8,3|7,4|6,6', goal: '7,2|9,3|7,4', boy: '8,2'}, {tree: '4,1|5,1|6,1|7,1|4,2|7,2|4,3|7,3|3,4|4,4|7,4|8,4|9,4|10,4|3,5|10,5|3,6|8,6|9,6|10,6|3,7|4,7|5,7|8,7|5,8|6,8|7,8|8,8', box: '5,5|6,5|6,6', goal: '5,4|7,5|9,5', boy: '5,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|4,3|6,3|8,3|9,3|10,3|4,4|10,4|4,5|10,5|4,6|8,6|9,6|10,6|4,7|5,7|6,7|7,7|8,7', box: '6,4|7,4|7,5', goal: '5,2|6,4|8,5', boy: '7,6'}, {tree: '6,1|7,1|8,1|9,1|10,1|6,2|10,2|6,3|8,3|10,3|4,4|5,4|6,4|10,4|4,5|10,5|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,5|8,5|8,6', goal: '9,3|9,4|7,6', boy: '5,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|3,3|6,3|8,3|9,3|10,3|3,4|10,4|3,5|7,5|8,5|10,5|3,6|4,6|10,6|4,7|5,7|9,7|10,7|5,8|6,8|7,8|8,8|9,8', box: '5,3|5,4|7,4', goal: '5,4|5,6|8,6', boy: '7,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|10,2|4,3|7,3|10,3|4,4|10,4|4,5|8,5|10,5|4,6|5,6|6,6|10,6|6,7|7,7|8,7|9,7|10,7', box: '8,4|6,5|7,5', goal: '5,4|9,5|9,6', boy: '8,2'}, {tree: '5,2|6,2|7,2|8,2|3,3|4,3|5,3|8,3|3,4|8,4|9,4|10,4|3,5|10,5|3,6|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,5|8,5|8,6', goal: '6,3|5,4|6,6', boy: '9,6'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|3,2|4,2|9,2|3,3|9,3|3,4|6,4|9,4|10,4|3,5|6,5|10,5|3,6|4,6|5,6|6,6|8,6|10,6|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '5,3|6,3|7,3', goal: '6,2|7,3|9,5', boy: '5,2'}, {tree: '7,1|8,1|9,1|10,1|7,2|10,2|5,3|6,3|7,3|10,3|5,4|10,4|3,5|4,5|5,5|8,5|10,5|3,6|10,6|3,7|7,7|10,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '8,3|5,6|8,6', goal: '9,3|8,4|9,5', boy: '8,7'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|9,2|3,3|9,3|3,4|6,4|7,4|9,4|10,4|3,5|4,5|7,5|10,5|4,6|10,6|4,7|7,7|8,7|9,7|10,7|4,8|5,8|6,8|7,8', box: '5,3|8,4|5,6', goal: '6,2|6,3|7,3', boy: '9,6'}, {tree: '5,1|6,1|7,1|8,1|5,2|8,2|5,3|8,3|9,3|10,3|3,4|4,4|5,4|10,4|3,5|7,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '6,5|7,6|8,6', goal: '7,4|8,4|6,6', boy: '8,7'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|9,2|3,3|5,3|9,3|10,3|3,4|10,4|3,5|4,5|5,5|10,5|5,6|10,6|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,3|6,4|6,5', goal: '7,3|6,4|9,6', boy: '8,3'}, {tree: '5,1|6,1|7,1|8,1|9,1|10,1|3,2|4,2|5,2|10,2|3,3|7,3|10,3|3,4|7,4|9,4|10,4|3,5|9,5|3,6|4,6|7,6|9,6|4,7|5,7|9,7|5,8|6,8|7,8|8,8|9,8', box: '5,3|6,4|6,5', goal: '7,2|8,3|6,5', boy: '6,3'}, {tree: '4,2|5,2|6,2|7,2|3,3|4,3|7,3|8,3|9,3|3,4|9,4|10,4|3,5|6,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,5|8,5|8,6', goal: '6,6|8,6|9,6', boy: '9,5'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|4,2|10,2|3,3|6,3|10,3|3,4|9,4|10,4|3,5|6,5|9,5|3,6|6,6|7,6|8,6|9,6|3,7|4,7|5,7|6,7', box: '5,4|6,4|7,4', goal: '4,3|8,4|5,5', boy: '5,2'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|10,2|3,3|5,3|7,3|8,3|10,3|3,4|5,4|10,4|3,5|10,5|3,6|4,6|5,6|6,6|7,6|10,6|7,7|10,7|7,8|8,8|9,8|10,8', box: '9,3|8,4|5,5', goal: '9,3|4,5|7,5', boy: '6,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|10,2|4,3|5,3|10,3|3,4|4,4|5,4|10,4|3,5|7,5|9,5|10,5|3,6|9,6|3,7|4,7|5,7|6,7|9,7|6,8|7,8|8,8|9,8', box: '6,3|5,5|8,5', goal: '7,4|5,6|8,6', boy: '5,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|9,2|10,2|4,3|10,3|4,4|5,4|10,4|5,5|10,5|5,6|6,6|8,6|10,6|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '7,3|6,4|7,4', goal: '9,4|8,5|9,7', boy: '6,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|9,2|10,2|3,3|10,3|3,4|6,4|10,4|3,5|6,5|7,5|9,5|10,5|3,6|6,6|7,6|9,6|3,7|9,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8', box: '5,3|6,3|8,6', goal: '5,4|7,4|8,7', boy: '5,7'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|3,3|8,3|3,4|6,4|8,4|9,4|10,4|3,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '6,5|7,5|5,6', goal: '5,3|5,4|6,6', boy: '5,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|7,2|10,2|3,3|10,3|3,4|6,4|10,4|3,5|9,5|10,5|3,6|4,6|5,6|8,6|9,6|5,7|8,7|5,8|6,8|7,8|8,8', box: '6,3|7,4|6,5', goal: '6,2|5,3|8,3', boy: '5,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|4,2|10,2|3,3|10,3|3,4|7,4|8,4|9,4|10,4|3,5|6,5|7,5|3,6|6,6|3,7|6,7|3,8|4,8|5,8|6,8', box: '5,3|8,3|5,4', goal: '8,2|4,4|6,4', boy: '9,3'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|4,3|7,3|9,3|4,4|9,4|10,4|4,5|5,5|7,5|10,5|4,6|8,6|10,6|4,7|10,7|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,4|6,5|7,7', goal: '6,2|5,7|7,7', boy: '8,3'}, {tree: '6,1|7,1|8,1|9,1|10,1|3,2|4,2|5,2|6,2|10,2|3,3|10,3|3,4|7,4|10,4|3,5|5,5|10,5|3,6|7,6|8,6|9,6|10,6|3,7|4,7|5,7|6,7|7,7', box: '5,3|5,4|8,5', goal: '8,2|5,3|8,3', boy: '6,3'}, {tree: '5,2|6,2|7,2|8,2|3,3|4,3|5,3|8,3|9,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|5,6|6,6|10,6|6,7|7,7|8,7|9,7|10,7', box: '8,4|6,5|7,5', goal: '5,4|6,4|9,4', boy: '9,5'}, {tree: '7,1|8,1|9,1|10,1|7,2|10,2|3,3|4,3|5,3|6,3|7,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|5,6|10,6|5,7|6,7|7,7|8,7|9,7|10,7', box: '5,4|7,4|9,4', goal: '9,3|7,5|7,6', boy: '8,2'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|7,2|10,2|3,3|5,3|10,3|3,4|10,4|3,5|4,5|5,5|6,5|7,5|10,5|5,6|10,6|5,7|10,7|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,3|9,3|7,4', goal: '6,3|8,5|9,7', boy: '9,6'}, {tree: '6,1|7,1|8,1|9,1|5,2|6,2|9,2|10,2|4,3|5,3|10,3|3,4|4,4|7,4|9,4|10,4|3,5|10,5|3,6|6,6|10,6|3,7|8,7|9,7|10,7|3,8|4,8|5,8|6,8|7,8|8,8', box: '6,4|8,4|7,5', goal: '8,3|9,3|8,5', boy: '7,2'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|3,3|7,3|8,3|9,3|10,3|3,4|10,4|3,5|4,5|6,5|8,5|10,5|3,6|8,6|10,6|3,7|10,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '5,3|6,3|5,4', goal: '7,4|7,5|4,6', boy: '7,2'}, {tree: '6,1|7,1|8,1|9,1|6,2|9,2|3,3|4,3|5,3|6,3|9,3|10,3|3,4|10,4|3,5|5,5|6,5|10,5|3,6|7,6|8,6|10,6|3,7|10,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '8,3|6,4|7,7', goal: '7,4|7,7|9,7', boy: '5,4'}, {tree: '6,1|7,1|8,1|9,1|10,1|6,2|10,2|4,3|5,3|6,3|10,3|4,4|9,4|10,4|3,5|4,5|9,5|3,6|7,6|9,6|3,7|9,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8', box: '6,4|8,4|6,5', goal: '4,6|4,7|5,7', boy: '8,2'}, {tree: '6,1|7,1|8,1|9,1|10,1|3,2|4,2|5,2|6,2|10,2|3,3|10,3|3,4|5,4|8,4|9,4|10,4|3,5|10,5|3,6|4,6|5,6|6,6|10,6|6,7|7,7|8,7|9,7|10,7', box: '7,3|5,5|7,5', goal: '7,2|6,3|9,5', boy: '9,2'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|7,2|10,2|3,3|5,3|10,3|3,4|7,4|10,4|3,5|4,5|10,5|4,6|7,6|8,6|9,6|10,6|4,7|5,7|6,7|7,7', box: '7,3|5,4|8,4', goal: '6,2|6,4|6,5', boy: '9,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|4,3|6,3|7,3|10,3|4,4|10,4|4,5|7,5|10,5|4,6|7,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '5,4|8,4|8,5', goal: '5,3|9,3|5,4', boy: '9,4'}, {tree: '3,1|4,1|5,1|6,1|3,2|6,2|3,3|6,3|3,4|6,4|7,4|8,4|9,4|10,4|3,5|10,5|3,6|8,6|10,6|3,7|4,7|5,7|10,7|5,8|6,8|7,8|8,8|9,8|10,8', box: '5,3|6,5|6,6', goal: '4,2|5,5|5,6', boy: '8,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|10,2|3,3|5,3|10,3|3,4|8,4|10,4|3,5|4,5|6,5|10,5|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '6,3|5,4|5,5', goal: '9,4|7,5|9,6', boy: '7,4'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|3,3|8,3|9,3|10,3|3,4|5,4|10,4|3,5|7,5|8,5|10,5|3,6|7,6|8,6|10,6|3,7|4,7|5,7|10,7|5,8|6,8|7,8|8,8|9,8|10,8', box: '6,4|7,4|5,6', goal: '6,2|8,4|4,5', boy: '4,6'}, {tree: '8,0|9,0|10,0|11,0|6,1|7,1|8,1|11,1|6,2|11,2|6,3|11,3|2,4|3,4|4,4|5,4|6,4|7,4|9,4|10,4|11,4|2,5|9,5|10,5|11,5|2,6|3,6|5,6|11,6|3,7|7,7|9,7|11,7|3,8|7,8|11,8|3,9|4,9|5,9|6,9|7,9|8,9|9,9|10,9|11,9', box: '9,3|7,6|9,6|5,7', goal: '9,1|10,1|9,2|10,2', boy: '3,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|9,2|10,2|11,2|3,3|11,3|3,4|4,4|11,4|4,5|5,5|6,5|7,5|9,5|11,5|7,6|11,6|7,7|8,7|9,7|10,7|11,7', box: '6,3|7,3|8,3|7,4', goal: '4,2|5,2|6,2|7,2', boy: '4,3'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|9,2|10,2|11,2|3,3|11,3|3,4|4,4|11,4|4,5|5,5|6,5|7,5|9,5|11,5|7,6|11,6|7,7|8,7|9,7|10,7|11,7', box: '6,3|7,3|8,3|7,4|8,5', goal: '4,2|5,2|6,2|7,2|10,3', boy: '4,3'}, {tree: '2,1|3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|2,2|6,2|7,2|10,2|2,3|10,3|11,3|2,4|7,4|11,4|2,5|7,5|11,5|2,6|5,6|7,6|8,6|9,6|10,6|11,6|2,7|3,7|7,7|3,8|4,8|5,8|6,8|7,8', box: '4,3|5,3|5,4|6,4|4,5|5,5', goal: '8,3|9,3|8,4|9,4|8,5|9,5', boy: '5,2'}, {tree: '2,0|3,0|4,0|5,0|2,1|5,1|6,1|7,1|2,2|7,2|8,2|9,2|10,2|11,2|12,2|2,3|12,3|2,4|3,4|4,4|7,4|8,4|9,4|12,4|2,5|3,5|4,5|7,5|11,5|12,5|2,6|11,6|2,7|7,7|8,7|11,7|2,8|6,8|7,8|8,8|11,8|2,9|3,9|4,9|5,9|6,9|8,9|9,9|10,9|11,9', box: '5,3|5,4|6,5|9,5|7,6|4,7|5,7', goal: '3,1|4,1|3,2|4,2|5,2|3,3|4,3', boy: '6,2'}, {tree: '3,0|4,0|5,0|6,0|7,0|8,0|9,0|10,0|11,0|2,1|3,1|7,1|8,1|11,1|2,2|7,2|8,2|11,2|2,3|5,3|6,3|7,3|8,3|11,3|2,4|8,4|11,4|2,5|5,5|8,5|11,5|2,6|7,6|8,6|11,6|2,7|3,7|4,7|11,7|4,8|5,8|6,8|7,8|11,8|7,9|8,9|9,9|10,9|11,9', box: '5,2|4,3|10,3|4,5|6,5|9,5|5,6|10,7', goal: '9,1|10,1|9,2|10,2|9,3|10,3|9,4|10,4', boy: '6,1'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|10,2|3,3|10,3|3,4|10,4|3,5|10,5|3,6|9,6|10,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7', box: '5,3|7,3|4,4|5,4|6,4|7,4|8,4|5,5', goal: '5,3|7,3|4,4|6,4|7,4|8,4|9,4|5,5', boy: '4,2'}, {tree: '5,1|6,1|7,1|8,1|9,1|10,1|5,2|10,2|3,3|4,3|5,3|10,3|3,4|10,4|3,5|8,5|10,5|3,6|6,6|8,6|9,6|10,6|3,7|8,7|3,8|4,8|5,8|6,8|7,8|8,8', box: '7,2|8,3|6,4|8,4|5,5|6,5|7,5', goal: '8,2|9,2|8,3|9,3|8,4|9,4|9,5', boy: '4,7'}, {tree: '4,1|5,1|6,1|7,1|8,1|3,2|4,2|8,2|9,2|10,2|11,2|3,3|11,3|3,4|8,4|11,4|2,5|3,5|5,5|6,5|11,5|2,6|6,6|10,6|11,6|2,7|8,7|9,7|10,7|2,8|3,8|4,8|5,8|6,8|7,8|8,8', box: '5,3|9,3|6,4|7,4|9,4|9,5|4,6', goal: '4,4|4,5|4,6|5,6|4,7|5,7|6,7', boy: '10,4'}, {tree: '3,0|4,0|5,0|6,0|7,0|8,0|3,1|8,1|2,2|3,2|8,2|9,2|2,3|5,3|9,3|2,4|7,4|9,4|10,4|2,5|6,5|7,5|10,5|11,5|12,5|2,6|3,6|12,6|3,7|4,7|5,7|6,7|12,7|6,8|7,8|8,8|9,8|10,8|11,8|12,8', box: '6,2|7,2|6,3|4,4|5,5|10,6', goal: '8,4|8,5|9,5|7,6|8,6|9,6', boy: '7,7'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|8,3|6,4|8,4|6,5|8,5', boy: '7,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|9,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|8,3|6,4|8,4|6,5|8,5', boy: '7,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|7,3|8,3|6,5|7,5|8,5', boy: '7,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|9,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|7,3|8,3|6,5|7,5|8,5', boy: '7,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|7,3|6,4|8,4|7,5|8,5', boy: '7,4'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|4,2|10,2|3,3|4,3|10,3|3,4|10,4|3,5|10,5|3,6|4,6|9,6|10,6|4,7|5,7|6,7|7,7|8,7|9,7', box: '7,3|8,3|6,4|8,4|6,5|7,5', goal: '6,3|7,3|6,4|8,4|7,5|8,5', boy: '7,4'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|3,2|9,2|10,2|3,3|10,3|3,4|10,4|3,5|9,5|10,5|3,6|9,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7', box: '5,3|6,3|7,3|8,3|5,4|5,5|6,5|7,5', goal: '5,3|6,3|5,4|6,4|7,4|5,5|6,5|7,5', boy: '6,4'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|3,2|9,2|10,2|3,3|10,3|3,4|7,4|10,4|3,5|9,5|10,5|3,6|9,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7', box: '6,3|7,3|8,3|5,4|6,5', goal: '5,3|6,3|5,4|5,5|6,5', boy: '8,4'}, {tree: '5,1|6,1|7,1|8,1|9,1|10,1|11,1|4,2|5,2|11,2|4,3|7,3|9,3|11,3|4,4|11,4|3,5|4,5|6,5|7,5|9,5|11,5|3,6|11,6|3,7|7,7|10,7|11,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '6,3|5,4|9,4|8,5|5,6', goal: '6,2|7,2|8,2|10,2|8,3', boy: '6,4'}, {tree: '5,1|6,1|7,1|8,1|9,1|10,1|11,1|4,2|5,2|11,2|4,3|7,3|9,3|11,3|4,4|9,4|11,4|3,5|4,5|6,5|7,5|9,5|11,5|3,6|11,6|3,7|7,7|10,7|11,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '8,3|8,5|8,6', goal: '6,2|7,2|8,2', boy: '4,7'}, {tree: '4,2|5,2|6,2|7,2|8,2|9,2|4,3|9,3|4,4|9,4|4,5|9,5|4,6|5,6|6,6|7,6|8,6|9,6', box: '5,4|6,4|7,4', goal: '6,3|5,5|7,5', boy: '8,5'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|9,2|10,2|11,2|2,3|3,3|11,3|2,4|7,4|8,4|9,4|10,4|11,4|2,5|7,5|2,6|3,6|7,6|3,7|4,7|5,7|6,7|7,7', box: '6,3|5,4|6,4', goal: '8,3|9,3|10,3', boy: '7,3'}, {tree: '4,2|5,2|6,2|7,2|8,2|9,2|4,3|9,3|4,4|9,4|4,5|9,5|4,6|5,6|6,6|7,6|8,6|9,6', box: '5,4|6,4|7,4', goal: '7,3|8,3|5,5', boy: '8,5'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|4,3|6,3|9,3|4,4|9,4|4,5|8,5|9,5|4,6|7,6|8,6|4,7|5,7|6,7|7,7', box: '7,3|6,4|6,5', goal: '5,2|6,2|7,2', boy: '5,6'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|4,3|9,3|4,4|9,4|4,5|7,5|8,5|9,5|4,6|5,6|7,6|5,7|6,7|7,7', box: '6,3|7,4|6,5', goal: '8,3|6,4|5,5', boy: '6,6'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|4,3|9,3|4,4|5,4|7,4|9,4|4,5|9,5|4,6|9,6|4,7|9,7|4,8|5,8|6,8|7,8|8,8|9,8', box: '6,3|8,4|6,5|7,5|7,6', goal: '8,6|5,7|6,7|7,7|8,7', boy: '7,2'}, {tree: '6,1|7,1|8,1|9,1|10,1|6,2|10,2|5,3|6,3|8,3|10,3|11,3|3,4|4,4|5,4|11,4|3,5|9,5|11,5|3,6|4,6|5,6|7,6|11,6|5,7|6,7|7,7|8,7|9,7|10,7|11,7', box: '7,4|7,5|8,5', goal: '4,5|5,5|6,5', boy: '6,6'}, {tree: '6,1|7,1|8,1|9,1|10,1|5,2|6,2|10,2|5,3|8,3|10,3|5,4|10,4|3,5|4,5|5,5|8,5|10,5|3,6|8,6|10,6|3,7|4,7|6,7|10,7|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,4|6,5|6,6', goal: '4,6|5,6|6,6', boy: '5,7'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|7,2|10,2|3,3|10,3|11,3|3,4|4,4|11,4|4,5|5,5|6,5|11,5|6,6|10,6|11,6|6,7|7,7|10,7|7,8|8,8|9,8|10,8', box: '6,3|6,4|7,4|8,4|8,5', goal: '4,2|5,2|6,2|5,3|6,3', boy: '5,4'}, {tree: '2,1|3,1|4,1|5,1|6,1|7,1|8,1|9,1|2,2|9,2|2,3|9,3|10,3|2,4|3,4|4,4|10,4|11,4|12,4|3,5|12,5|3,6|12,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|12,7|9,8|10,8|11,8|12,8', box: '6,2|4,3|7,3|6,4|5,5|7,5|8,5|9,5', goal: '6,2|5,3|7,3|6,4|7,4|5,5|6,5|7,5', boy: '8,2'}, {tree: '2,1|3,1|4,1|5,1|6,1|7,1|8,1|9,1|2,2|9,2|2,3|9,3|10,3|2,4|3,4|5,4|10,4|11,4|12,4|3,5|12,5|3,6|12,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|12,7|9,8|10,8|11,8|12,8', box: '7,2|4,3|7,3|6,4|7,4|5,5|7,5|10,5', goal: '6,2|5,3|7,3|6,4|7,4|5,5|6,5|7,5', boy: '8,2'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|3,2|8,2|3,3|8,3|9,3|10,3|3,4|10,4|3,5|4,5|5,5|10,5|5,6|10,6|5,7|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '5,3|6,3|7,3|5,4|7,4|7,5|8,6', goal: '4,2|5,2|6,2|7,2|4,3|6,3|5,4', boy: '4,4'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|3,3|8,3|9,3|10,3|3,4|10,4|3,5|4,5|5,5|10,5|5,6|10,6|5,7|6,7|7,7|10,7|7,8|8,8|9,8|10,8', box: '5,3|6,3|5,4|7,4|7,5|8,6', goal: '4,2|5,2|6,2|4,3|5,4|9,4', boy: '4,4'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|9,2|10,2|11,2|12,2|2,3|3,3|12,3|2,4|7,4|8,4|9,4|10,4|11,4|12,4|2,5|7,5|2,6|3,6|7,6|3,7|4,7|5,7|6,7|7,7', box: '10,3|5,4|6,4', goal: '9,3|10,3|11,3', boy: '11,3'}, {tree: '5,2|6,2|7,2|8,2|9,2|10,2|4,3|5,3|10,3|4,4|8,4|10,4|4,5|10,5|4,6|7,6|9,6|10,6|4,7|9,7|4,8|5,8|6,8|7,8|8,8|9,8', box: '6,4|7,5|8,6', goal: '8,3|6,5|5,7', boy: '7,7'}, {tree: '4,2|5,2|6,2|7,2|8,2|9,2|10,2|4,3|10,3|4,4|6,4|8,4|10,4|4,5|10,5|4,6|9,6|10,6|4,7|7,7|8,7|9,7|4,8|5,8|6,8|7,8', box: '8,5|6,6|7,6', goal: '5,3|7,4|5,6', boy: '8,3'}, {tree: '4,1|5,1|6,1|8,1|9,1|10,1|4,2|6,2|7,2|8,2|10,2|4,3|6,3|10,3|4,4|10,4|4,5|10,5|4,6|7,6|10,6|4,7|7,7|8,7|9,7|10,7|4,8|5,8|6,8|7,8', box: '6,4|7,4|7,5', goal: '5,2|9,2|9,3', boy: '9,4'}, {tree: '6,1|7,1|8,1|9,1|6,2|9,2|10,2|3,3|4,3|5,3|6,3|10,3|3,4|6,4|10,4|3,5|9,5|10,5|3,6|8,6|9,6|3,7|4,7|8,7|4,8|5,8|6,8|7,8|8,8', box: '7,4|8,4|7,6', goal: '4,4|4,6|5,7', boy: '8,2'}, {tree: '3,2|4,2|5,2|6,2|7,2|3,3|7,3|8,3|9,3|10,3|3,4|10,4|3,5|6,5|8,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|7,7|8,7|9,7|10,7', box: '5,4|7,5|8,6', goal: '5,3|6,3|7,6', boy: '5,6'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|9,2|3,3|9,3|3,4|7,4|9,4|10,4|3,5|5,5|10,5|3,6|8,6|10,6|3,7|4,7|5,7|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '6,4|7,5|7,6', goal: '4,3|8,3|8,5', boy: '7,3'}, {tree: '4,2|5,2|6,2|7,2|8,2|4,3|8,3|9,3|10,3|4,4|6,4|10,4|4,5|10,5|4,6|7,6|10,6|4,7|5,7|9,7|10,7|5,8|6,8|7,8|8,8|9,8', box: '7,4|8,4|6,6', goal: '5,3|7,3|5,4', boy: '8,5'}, {tree: '3,2|4,2|5,2|6,2|7,2|8,2|9,2|10,2|3,3|10,3|3,4|5,4|7,4|10,4|3,5|10,5|3,6|4,6|5,6|6,6|7,6|10,6|7,7|10,7|7,8|8,8|9,8|10,8', box: '5,5|8,5|9,6', goal: '4,3|8,3|9,5', boy: '4,5'}, {tree: '4,2|5,2|6,2|7,2|8,2|4,3|8,3|9,3|10,3|3,4|4,4|10,4|3,5|10,5|3,6|4,6|6,6|8,6|9,6|10,6|4,7|8,7|4,8|5,8|6,8|7,8|8,8', box: '6,5|8,5|5,6', goal: '6,4|4,5|7,5', boy: '6,3'}, {tree: '4,2|5,2|6,2|7,2|3,3|4,3|7,3|8,3|9,3|10,3|3,4|10,4|3,5|5,5|10,5|3,6|7,6|10,6|3,7|4,7|5,7|6,7|7,7|10,7|7,8|8,8|9,8|10,8', box: '6,4|6,5|8,5', goal: '4,4|5,4|9,4', boy: '4,6'}, {tree: '4,1|5,1|6,1|7,1|4,2|7,2|4,3|7,3|3,4|4,4|7,4|8,4|9,4|10,4|3,5|10,5|3,6|8,6|9,6|10,6|3,7|4,7|5,7|8,7|5,8|6,8|7,8|8,8', box: '5,5|6,5|6,6', goal: '5,4|7,5|9,5', boy: '5,2'}, {tree: '6,2|7,2|8,2|9,2|10,2|6,3|10,3|6,4|8,4|10,4|4,5|5,5|6,5|10,5|4,6|10,6|4,7|10,7|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,6|8,6|8,7', goal: '9,4|9,5|7,7', boy: '5,6'}, {tree: '4,2|5,2|6,2|7,2|8,2|9,2|4,3|9,3|10,3|4,4|7,4|10,4|4,5|10,5|4,6|8,6|10,6|4,7|5,7|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '8,5|6,6|7,6', goal: '5,5|9,6|9,7', boy: '7,3'}, {tree: '5,3|6,3|7,3|8,3|3,4|4,4|5,4|8,4|3,5|8,5|9,5|10,5|3,6|10,6|3,7|4,7|10,7|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,6|8,6|8,7', goal: '6,4|5,5|6,7', boy: '9,7'}, {tree: '7,1|8,1|9,1|10,1|7,2|10,2|5,3|6,3|7,3|10,3|5,4|10,4|3,5|4,5|5,5|8,5|10,5|3,6|10,6|3,7|7,7|10,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8|10,8', box: '8,3|5,6|8,6', goal: '9,3|8,4|9,5', boy: '9,7'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|9,2|3,3|9,3|3,4|6,4|7,4|9,4|10,4|3,5|4,5|7,5|10,5|4,6|10,6|4,7|7,7|8,7|9,7|10,7|4,8|5,8|6,8|7,8', box: '5,3|8,4|5,6', goal: '6,2|6,3|7,3', boy: '9,6'}, {tree: '4,2|5,2|6,2|7,2|8,2|9,2|10,2|3,3|4,3|10,3|3,4|6,4|10,4|3,5|9,5|10,5|3,6|6,6|9,6|3,7|6,7|7,7|8,7|9,7|3,8|4,8|5,8|6,8', box: '5,5|6,5|7,5', goal: '4,4|8,5|5,6', boy: '5,3'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|4,2|9,2|10,2|4,3|5,3|10,3|3,4|4,4|5,4|10,4|3,5|7,5|9,5|10,5|3,6|9,6|3,7|4,7|5,7|6,7|9,7|6,8|7,8|8,8|9,8', box: '6,3|5,5|8,5', goal: '7,4|5,6|8,6', boy: '5,2'}, {tree: '4,1|5,1|6,1|7,1|8,1|4,2|8,2|9,2|10,2|4,3|10,3|4,4|5,4|10,4|5,5|10,5|5,6|6,6|8,6|10,6|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '7,3|6,4|7,4', goal: '9,4|8,5|9,7', boy: '6,5'}, {tree: '3,1|4,1|5,1|6,1|7,1|3,2|7,2|8,2|9,2|10,2|3,3|10,3|3,4|6,4|10,4|3,5|6,5|7,5|9,5|10,5|3,6|6,6|7,6|9,6|3,7|9,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8', box: '5,3|6,3|8,6', goal: '5,4|7,4|8,7', boy: '5,7'}, {tree: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|4,2|10,2|3,3|10,3|3,4|7,4|8,4|9,4|10,4|3,5|6,5|7,5|3,6|6,6|3,7|6,7|3,8|4,8|5,8|6,8', box: '5,3|8,3|5,4', goal: '8,2|4,4|6,4', boy: '9,3'}, {tree: '5,3|6,3|7,3|8,3|3,4|4,4|5,4|8,4|9,4|10,4|3,5|10,5|3,6|10,6|3,7|4,7|5,7|6,7|10,7|6,8|7,8|8,8|9,8|10,8', box: '8,5|6,6|7,6', goal: '5,5|6,5|9,5', boy: '9,6'}, {tree: '3,1|4,1|5,1|6,1|7,1|8,1|9,1|10,1|3,2|7,2|10,2|3,3|5,3|10,3|3,4|10,4|3,5|4,5|5,5|6,5|7,5|10,5|5,6|10,6|5,7|10,7|5,8|6,8|7,8|8,8|9,8|10,8', box: '7,3|9,3|7,4', goal: '6,3|8,5|9,7', boy: '9,5'}, {tree: '6,1|7,1|8,1|9,1|10,1|6,2|10,2|4,3|5,3|6,3|10,3|4,4|9,4|10,4|3,5|4,5|9,5|3,6|7,6|9,6|3,7|9,7|3,8|4,8|5,8|6,8|7,8|8,8|9,8', box: '6,4|8,4|6,5', goal: '4,6|4,7|5,7', boy: '9,3'}, {tree: '1,1|1,2|1,3|1,4|3,4|4,4|5,4|11,4|12,4|13,4|1,5|3,5|5,5|11,5|1,6|3,6|5,6|11,6|12,6|13,6|1,7|3,7|5,7|11,7|1,8|3,8|4,8|5,8|11,8|12,8|13,8', box: '4,1|5,1|6,1|7,1|8,1|9,1|10,1|11,1|12,1', goal: '7,4|9,4|7,5|9,5|7,6|9,6|7,7|9,7|8,8', boy: '8,5'}];
2 |
3 | export default function getData(level) {
4 | const {tree, box, goal, boy} = gameData[level - 1];
5 | const [trees, buckets, spots] = [tree, box, goal].map((data) => {
6 | return data.split('|').map(t => t.split(',').map(Number));
7 | });
8 | const man = boy.split(',').map(Number);
9 | return {trees, buckets, spots, man};
10 | }
--------------------------------------------------------------------------------
/js/app.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Boxman=t():e.Boxman=t()}(window,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/js/",n(n.s=16)}([function(e,t,n){e.exports=n(8)},function(e,t,n){var o=n(9),r=n(10),i=n(11);e.exports=function(e,t){return o(e)||r(e,t)||i()}},function(e,t){function n(e,t,n,o,r,i,a){try{var s=e[i](a),u=s.value}catch(e){return void n(e)}s.done?t(u):Promise.resolve(u).then(o,r)}e.exports=function(e){return function(){var t=this,o=arguments;return new Promise(function(r,i){var a=e.apply(t,o);function s(e){n(a,r,i,s,u,"next",e)}function u(e){n(a,r,i,s,u,"throw",e)}s(void 0)})}}},function(e,t,n){(function(n){var o;
2 | /*!
3 | * howler.js v2.1.1
4 | * howlerjs.com
5 | *
6 | * (c) 2013-2018, James Simpson of GoldFire Studios
7 | * goldfirestudios.com
8 | *
9 | * MIT License
10 | */
11 | /*!
12 | * howler.js v2.1.1
13 | * howlerjs.com
14 | *
15 | * (c) 2013-2018, James Simpson of GoldFire Studios
16 | * goldfirestudios.com
17 | *
18 | * MIT License
19 | */
20 | !function(){"use strict";var r=function(){this.init()};r.prototype={init:function(){var e=this||i;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var t=this||i;if(e=parseFloat(e),t.ctx||f(),void 0!==e&&e>=0&&e<=1){if(t._volume=e,t._muted)return t;t.usingWebAudio&&t.masterGain.gain.setValueAtTime(e,i.ctx.currentTime);for(var n=0;n=0;t--)e._howls[t].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,f()),e},codecs:function(e){return(this||i)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||i;if(e.state=e.ctx&&e.ctx.state||"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{void 0===(new Audio).oncanplaythrough&&(e._canPlayEvent="canplay")}catch(t){e.noAudio=!0}else e.noAudio=!0;try{(new Audio).muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||i,t=null;try{t="undefined"!=typeof Audio?new Audio:null}catch(t){return e}if(!t||"function"!=typeof t.canPlayType)return e;var n=t.canPlayType("audio/mpeg;").replace(/^no$/,""),o=e._navigator&&e._navigator.userAgent.match(/OPR\/([0-6].)/g),r=o&&parseInt(o[0].split("/")[1],10)<33;return e._codecs={mp3:!(r||!n&&!t.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!n,opus:!!t.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!t.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!t.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!t.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),aac:!!t.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!t.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(t.canPlayType("audio/x-m4a;")||t.canPlayType("audio/m4a;")||t.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(t.canPlayType("audio/x-mp4;")||t.canPlayType("audio/mp4;")||t.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!!t.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,""),webm:!!t.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,""),dolby:!!t.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(t.canPlayType("audio/x-flac;")||t.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||i,t=/iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi|Chrome|Safari/i.test(e._navigator&&e._navigator.userAgent);if(!e._audioUnlocked&&e.ctx&&t){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var n=function(t){for(var o=0;o0?s._seek:n._sprite[e][0]/1e3),c=Math.max(0,(n._sprite[e][0]+n._sprite[e][1])/1e3-l),d=1e3*c/Math.abs(s._rate),_=n._sprite[e][0]/1e3,f=(n._sprite[e][0]+n._sprite[e][1])/1e3,p=!(!s._loop&&!n._sprite[e][2]);s._sprite=e,s._ended=!1;var h=function(){s._paused=!1,s._seek=l,s._start=_,s._stop=f,s._loop=p};if(!(l>=f)){var m=s._node;if(n._webAudio){var v=function(){n._playLock=!1,h(),n._refreshBuffer(s);var e=s._muted||n._muted?0:s._volume;m.gain.setValueAtTime(e,i.ctx.currentTime),s._playStart=i.ctx.currentTime,void 0===m.bufferSource.start?s._loop?m.bufferSource.noteGrainOn(0,l,86400):m.bufferSource.noteGrainOn(0,l,c):s._loop?m.bufferSource.start(0,l,86400):m.bufferSource.start(0,l,c),d!==1/0&&(n._endTimers[s._id]=setTimeout(n._ended.bind(n,s),d)),t||setTimeout(function(){n._emit("play",s._id),n._loadQueue()},0)};"running"===i.state?v():(n._playLock=!0,n.once("resume",v),n._clearTimer(s._id))}else{var y=function(){m.currentTime=l,m.muted=s._muted||n._muted||i._muted||m.muted,m.volume=s._volume*i.volume(),m.playbackRate=s._rate;try{var o=m.play();if(o&&"undefined"!=typeof Promise&&(o instanceof Promise||"function"==typeof o.then)?(n._playLock=!0,h(),o.then(function(){n._playLock=!1,m._unlocked=!0,t||(n._emit("play",s._id),n._loadQueue())}).catch(function(){n._playLock=!1,n._emit("playerror",s._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction."),s._ended=!0,s._paused=!0})):t||(n._playLock=!1,h(),n._emit("play",s._id),n._loadQueue()),m.playbackRate=s._rate,m.paused)return void n._emit("playerror",s._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.");"__default"!==e||s._loop?n._endTimers[s._id]=setTimeout(n._ended.bind(n,s),d):(n._endTimers[s._id]=function(){n._ended(s),m.removeEventListener("ended",n._endTimers[s._id],!1)},m.addEventListener("ended",n._endTimers[s._id],!1))}catch(e){n._emit("playerror",s._id,e)}},b=window&&window.ejecta||!m.readyState&&i._navigator.isCocoonJS;if(m.readyState>=3||b)y();else{n._playLock=!0;var g=function(){y(),m.removeEventListener(i._canPlayEvent,g,!1)};m.addEventListener(i._canPlayEvent,g,!1),n._clearTimer(s._id)}}return s._id}n._ended(s)},pause:function(e){var t=this;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"pause",action:function(){t.pause(e)}}),t;for(var n=t._getSoundIds(e),o=0;o=0?t=parseInt(r[0],10):e=parseFloat(r[0]):r.length>=2&&(e=parseFloat(r[0]),t=parseInt(r[1],10)),!(void 0!==e&&e>=0&&e<=1))return(n=t?o._soundById(t):o._sounds[0])?n._volume:0;if("loaded"!==o._state||o._playLock)return o._queue.push({event:"volume",action:function(){o.volume.apply(o,r)}}),o;void 0===t&&(o._volume=e),t=o._getSoundIds(t);for(var a=0;a0?o/l:o),d=Date.now();e._fadeTo=n,e._interval=setInterval(function(){var r=(Date.now()-d)/o;d=Date.now(),s+=u*r,s=Math.max(0,s),s=Math.min(1,s),s=Math.round(100*s)/100,a._webAudio?e._volume=s:a.volume(s,e._id,!0),i&&(a._volume=s),(nt&&s>=n)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,a.volume(n,e._id),a._emit("fade",e._id))},c)},_stopFade:function(e){var t=this._soundById(e);return t&&t._interval&&(this._webAudio&&t._node.gain.cancelScheduledValues(i.ctx.currentTime),clearInterval(t._interval),t._interval=null,this.volume(t._fadeTo,e),t._fadeTo=null,this._emit("fade",e)),this},loop:function(){var e,t,n,o=arguments;if(0===o.length)return this._loop;if(1===o.length){if("boolean"!=typeof o[0])return!!(n=this._soundById(parseInt(o[0],10)))&&n._loop;e=o[0],this._loop=e}else 2===o.length&&(e=o[0],t=parseInt(o[1],10));for(var r=this._getSoundIds(t),i=0;i=0?t=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),t=parseInt(r[1],10));if("number"!=typeof e)return(n=o._soundById(t))?n._rate:o._rate;if("loaded"!==o._state||o._playLock)return o._queue.push({event:"rate",action:function(){o.rate.apply(o,r)}}),o;void 0===t&&(o._rate=e),t=o._getSoundIds(t);for(var a=0;a=0?t=parseInt(o[0],10):n._sounds.length&&(t=n._sounds[0]._id,e=parseFloat(o[0]))}else 2===o.length&&(e=parseFloat(o[0]),t=parseInt(o[1],10));if(void 0===t)return n;if("loaded"!==n._state||n._playLock)return n._queue.push({event:"seek",action:function(){n.seek.apply(n,o)}}),n;var r=n._soundById(t);if(r){if(!("number"==typeof e&&e>=0)){if(n._webAudio){var a=n.playing(t)?i.ctx.currentTime-r._playStart:0,s=r._rateSeek?r._rateSeek-r._seek:0;return r._seek+(s+a*Math.abs(r._rate))}return r._node.currentTime}var u=n.playing(t);u&&n.pause(t,!0),r._seek=e,r._ended=!1,n._clearTimer(t),n._webAudio||!r._node||isNaN(r._node.duration)||(r._node.currentTime=e);var l=function(){n._emit("seek",t),u&&n.play(t,!0)};if(u&&!n._webAudio){var c=function(){n._playLock?setTimeout(c,0):l()};setTimeout(c,0)}else l()}return n},playing:function(e){if("number"==typeof e){var t=this._soundById(e);return!!t&&!t._paused}for(var n=0;n=0&&i._howls.splice(o,1);var r=!0;for(n=0;n=0){r=!1;break}return u&&r&&delete u[e._src],i.noAudio=!1,e._state="unloaded",e._sounds=[],e=null,null},on:function(e,t,n,o){var r=this["_on"+e];return"function"==typeof t&&r.push(o?{id:n,fn:t,once:o}:{id:n,fn:t}),this},off:function(e,t,n){var o=this["_on"+e],r=0;if("number"==typeof t&&(n=t,t=null),t||n)for(r=0;r=0;r--)o[r].id&&o[r].id!==t&&"load"!==e||(setTimeout(function(e){e.call(this,t,n)}.bind(this,o[r].fn),0),o[r].once&&this.off(e,o[r].fn,o[r].id));return this._loadQueue(e),this},_loadQueue:function(e){if(this._queue.length>0){var t=this._queue[0];t.event===e&&(this._queue.shift(),this._loadQueue()),e||t.action()}return this},_ended:function(e){var t=e._sprite;if(!this._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;n--){if(t<=e)return;this._sounds[n]._ended&&(this._webAudio&&this._sounds[n]._node&&this._sounds[n]._node.disconnect(0),this._sounds.splice(n,1),t--)}}},_getSoundIds:function(e){if(void 0===e){for(var t=[],n=0;n=0;if(i._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),t))try{e.bufferSource.buffer=i._scratchBuffer}catch(e){}return e.bufferSource=null,this}};var s=function(e){this._parent=e,this.init()};s.prototype={init:function(){var e=this._parent;return this._muted=e._muted,this._loop=e._loop,this._volume=e._volume,this._rate=e._rate,this._seek=0,this._paused=!0,this._ended=!0,this._sprite="__default",this._id=++i._counter,e._sounds.push(this),this.create(),this},create:function(){var e=this._parent,t=i._muted||this._muted||this._parent._muted?0:this._volume;return e._webAudio?(this._node=void 0===i.ctx.createGain?i.ctx.createGainNode():i.ctx.createGain(),this._node.gain.setValueAtTime(t,i.ctx.currentTime),this._node.paused=!0,this._node.connect(i.masterGain)):(this._node=i._obtainHtml5Audio(),this._errorFn=this._errorListener.bind(this),this._node.addEventListener("error",this._errorFn,!1),this._loadFn=this._loadListener.bind(this),this._node.addEventListener(i._canPlayEvent,this._loadFn,!1),this._node.src=e._src,this._node.preload="auto",this._node.volume=t*i.volume(),this._node.load()),this},reset:function(){var e=this._parent;return this._muted=e._muted,this._loop=e._loop,this._volume=e._volume,this._rate=e._rate,this._seek=0,this._rateSeek=0,this._paused=!0,this._ended=!0,this._sprite="__default",this._id=++i._counter,this},_errorListener:function(){this._parent._emit("loaderror",this._id,this._node.error?this._node.error.code:0),this._node.removeEventListener("error",this._errorFn,!1)},_loadListener:function(){var e=this._parent;e._duration=Math.ceil(10*this._node.duration)/10,0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue()),this._node.removeEventListener(i._canPlayEvent,this._loadFn,!1)}};var u={},l=function(e){var t=e._src;if(u[t])return e._duration=u[t].duration,void _(e);if(/^data:[^;]+;base64,/.test(t)){for(var n=atob(t.split(",")[1]),o=new Uint8Array(n.length),r=0;r0?(u[t._src]=e,_(t,e)):n()};"undefined"!=typeof Promise&&1===i.ctx.decodeAudioData.length?i.ctx.decodeAudioData(e).then(o).catch(n):i.ctx.decodeAudioData(e,o,n)},_=function(e,t){t&&!e._duration&&(e._duration=t.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue())},f=function(){if(i.usingWebAudio){try{"undefined"!=typeof AudioContext?i.ctx=new AudioContext:"undefined"!=typeof webkitAudioContext?i.ctx=new webkitAudioContext:i.usingWebAudio=!1}catch(e){i.usingWebAudio=!1}i.ctx||(i.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(i._navigator&&i._navigator.platform),t=i._navigator&&i._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),n=t?parseInt(t[1],10):null;if(e&&n&&n<9){var o=/safari/.test(i._navigator&&i._navigator.userAgent.toLowerCase());(i._navigator&&i._navigator.standalone&&!o||i._navigator&&!i._navigator.standalone&&!o)&&(i.usingWebAudio=!1)}i.usingWebAudio&&(i.masterGain=void 0===i.ctx.createGain?i.ctx.createGainNode():i.ctx.createGain(),i.masterGain.gain.setValueAtTime(i._muted?0:1,i.ctx.currentTime),i.masterGain.connect(i.ctx.destination)),i._setup()}};void 0===(o=function(){return{Howler:i,Howl:a}}.apply(t,[]))||(e.exports=o),t.Howler=i,t.Howl=a,"undefined"!=typeof window?(window.HowlerGlobal=r,window.Howler=i,window.Howl=a,window.Sound=s):void 0!==n&&(n.HowlerGlobal=r,n.Howler=i,n.Howl=a,n.Sound=s)}(),
21 | /*!
22 | * Spatial Plugin - Adds support for stereo and 3D audio where Web Audio is supported.
23 | *
24 | * howler.js v2.1.1
25 | * howlerjs.com
26 | *
27 | * (c) 2013-2018, James Simpson of GoldFire Studios
28 | * goldfirestudios.com
29 | *
30 | * MIT License
31 | */
32 | function(){"use strict";var e;HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){if(!this.ctx||!this.ctx.listener)return this;for(var t=this._howls.length-1;t>=0;t--)this._howls[t].stereo(e);return this},HowlerGlobal.prototype.pos=function(e,t,n){return this.ctx&&this.ctx.listener?(t="number"!=typeof t?this._pos[1]:t,n="number"!=typeof n?this._pos[2]:n,"number"!=typeof e?this._pos:(this._pos=[e,t,n],void 0!==this.ctx.listener.positionX?(this.ctx.listener.positionX.setTargetAtTime(this._pos[0],Howler.ctx.currentTime,.1),this.ctx.listener.positionY.setTargetAtTime(this._pos[1],Howler.ctx.currentTime,.1),this.ctx.listener.positionZ.setTargetAtTime(this._pos[2],Howler.ctx.currentTime,.1)):this.ctx.listener.setPosition(this._pos[0],this._pos[1],this._pos[2]),this)):this},HowlerGlobal.prototype.orientation=function(e,t,n,o,r,i){if(!this.ctx||!this.ctx.listener)return this;var a=this._orientation;return t="number"!=typeof t?a[1]:t,n="number"!=typeof n?a[2]:n,o="number"!=typeof o?a[3]:o,r="number"!=typeof r?a[4]:r,i="number"!=typeof i?a[5]:i,"number"!=typeof e?a:(this._orientation=[e,t,n,o,r,i],void 0!==this.ctx.listener.forwardX?(this.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),this.ctx.listener.forwardY.setTargetAtTime(t,Howler.ctx.currentTime,.1),this.ctx.listener.forwardZ.setTargetAtTime(n,Howler.ctx.currentTime,.1),this.ctx.listener.upX.setTargetAtTime(e,Howler.ctx.currentTime,.1),this.ctx.listener.upY.setTargetAtTime(t,Howler.ctx.currentTime,.1),this.ctx.listener.upZ.setTargetAtTime(n,Howler.ctx.currentTime,.1)):this.ctx.listener.setOrientation(e,t,n,o,r,i),this)},Howl.prototype.init=(e=Howl.prototype.init,function(t){return this._orientation=t.orientation||[1,0,0],this._stereo=t.stereo||null,this._pos=t.pos||null,this._pannerAttr={coneInnerAngle:void 0!==t.coneInnerAngle?t.coneInnerAngle:360,coneOuterAngle:void 0!==t.coneOuterAngle?t.coneOuterAngle:360,coneOuterGain:void 0!==t.coneOuterGain?t.coneOuterGain:0,distanceModel:void 0!==t.distanceModel?t.distanceModel:"inverse",maxDistance:void 0!==t.maxDistance?t.maxDistance:1e4,panningModel:void 0!==t.panningModel?t.panningModel:"HRTF",refDistance:void 0!==t.refDistance?t.refDistance:1,rolloffFactor:void 0!==t.rolloffFactor?t.rolloffFactor:1},this._onstereo=t.onstereo?[{fn:t.onstereo}]:[],this._onpos=t.onpos?[{fn:t.onpos}]:[],this._onorientation=t.onorientation?[{fn:t.onorientation}]:[],e.call(this,t)}),Howl.prototype.stereo=function(e,n){var o=this;if(!o._webAudio)return o;if("loaded"!==o._state)return o._queue.push({event:"stereo",action:function(){o.stereo(e,n)}}),o;var r=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===n){if("number"!=typeof e)return o._stereo;o._stereo=e,o._pos=[e,0,0]}for(var i=o._getSoundIds(n),a=0;a=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return r("end");if(a.tryLoc<=this.prev){var u=o.call(a,"catchLoc"),l=o.call(a,"finallyLoc");if(u&&l){if(this.prev=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),S(n),p}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var o=n.completion;if("throw"===o.type){var r=o.arg;S(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:L(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),p}},e}(e.exports);try{regeneratorRuntime=o}catch(e){Function("r","regeneratorRuntime = r")(o)}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){var n=[],o=!0,r=!1,i=void 0;try{for(var a,s=e[Symbol.iterator]();!(o=(a=s.next()).done)&&(n.push(a.value),!t||n.length!==t);o=!0);}catch(e){r=!0,i=e}finally{try{o||null==s.return||s.return()}finally{if(r)throw i}}return n}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t0&&a(e-1),n=e%o1&&void 0!==arguments[1]?arguments[1]:1;return[function(e,n){return[e-t,n]},function(e,n){return[e+t,n]},function(e,n){return[e,n-t]},function(e,n){return[e,n+t]}][e]}function p(e,t,n){return e<0||e>=o?null:t<0||t>=r?null:t*o+e}var h=null,m=Number(e.man[0]),v=Number(e.man[1]),y={};function b(e,t){return null==y[e]?null:y[e][t]}function g(e,t,n){var o=b(e,t)||[0,0,0,0,0];x(o,n),y[e]=y[e]||{},y[e][t]=o}function x(e,t){for(var n=0;t>=30;)t-=30,n++;e[n]|=1<>>8&255,e>>>16&255,e>>>24&255,255&t,t>>>8&255,t>>>16&255,t>>>24&255],i=-1;return 4294967295!==o&&(i=n>>16&255),{buckets:r=new Set(r.filter(function(e){return 255!==e})),x:255&n,y:n>>8&255,step:i,pre:o}}var T=new Uint32Array(268435456),k=w({buckets:a,pre:-1,x:m,y:v});T[0]=k[0],T[1]=k[1],T[2]=k[2],T[3]=k[3],g(T[0],T[1],p(m,v));var S=4;function I(e,t,n,o,r){var i=function(e){var t=f(e),n=f(e,2);return function(e,o,r){var i=t(o,r),a=p(i[0],i[1]);if(a&&u(e,a))return c;if(a&&e.has(a)){var s=p((i=n(o,r))[0],i[1]);if(s&&u(e,s))return _(e,s,a)}return 0}}(r),a=f(r),l=new Set(e),m=i(l,n,o);if(m){var v=a(n,o);if(m===d&&function(e){return s.every(function(t){return e.has(t)})}(l))return h=function e(t){var n=A(T[t],T[t+1],T[t+2],T[t+3]);return n.step>=0?e(n.pre).concat(n.step):[]}(t).concat(r),!0;var y=w({buckets:l,pre:t,step:r,x:v[0],y:v[1]}),k=b(y[0],y[1]);if(k){var I=p(v[0],v[1]);(function(e,t){for(var n=0;t>=30;)t-=30,n++;return e[n]&1<=15||t>=10}},{key:"isEmpty",value:function(e,t){return!this.isOutOfBound(e,t)&&!this.getItem(e,t)}},{key:"isAtSpot",value:function(e){for(var t=this.container.querySelectorAll(".spot"),n=0;n0&&void 0!==s[0]?s[0]:"right",n=this.boxman,o=Number(n.dataset.x),i=Number(n.dataset.y),a=null,"left"===t?a=this.getItem(o-1,i):"right"===t?a=this.getItem(o+1,i):"up"===t?a=this.getItem(o,i-1):"down"===t&&(a=this.getItem(o,i+1)),a){e.next=13;break}return this.onmove&&this.onmove([n],t),n.className="boxman ".concat(t," walk"),e.next=10,this.moveItem(n,t);case 10:n.className="boxman ".concat(t),e.next=22;break;case 13:if("bucket"!==a.className||!("left"===t&&this.isEmpty(o-2,i)||"right"===t&&this.isEmpty(o+2,i)||"up"===t&&this.isEmpty(o,i-2)||"down"===t&&this.isEmpty(o,i+2))){e.next=21;break}return this.onmove&&this.onmove([n,a],t),n.className="boxman ".concat(t," walk"),e.next=18,Promise.all([this.moveItem(n,t),this.moveItem(a,t)]);case 18:n.className="boxman ".concat(t),e.next=22;break;case 21:n.className="boxman ".concat(t);case 22:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"moveItem",value:function(t){var n,o,r,i=this,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"right";return"left"===a||"right"===a?(n=Number(t.dataset.x),o="left"===a?n-1:n+1,r="left"):(n=Number(t.dataset.y),o="up"===a?n-1:n+1,r="top"),new Promise(function(a){var s=Date.now(),u=i;requestAnimationFrame(function i(){var l=Math.min(1,(Date.now()-s)/200);t.style[r]="".concat(e.ITEM_WIDTH*((1-l)*n+l*o),"px"),l<1?requestAnimationFrame(i):("left"===r?u.moveTo(t,o,t.dataset.y):u.moveTo(t,t.dataset.x,o),a())})})}},{key:"isWin",value:function(){var e=this,t=this.container.querySelectorAll(".bucket");return Array.from(t).every(function(t){return e.isAtSpot(t)})}},{key:"waitCommand",value:function(){var e=this;return new Promise(function(t){e._command&&window.removeEventListener("keydown",e._command),e._command=function(e){switch(e.keyCode){case 37:t("left");break;case 38:t("up");break;case 39:t("right");break;case 40:t("down");break;default:t(null)}},window.addEventListener("keydown",e._command,{once:!0})})}},{key:"clear",value:function(){this.container.innerHTML=""}},{key:"solve",value:function(){var e=a()(r.a.mark(function e(){var t,n,o,i,a=arguments;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t=a.length>0&&void 0!==a[0]?a[0]:this.level,n="solved".concat(t),!(o=localStorage.getItem(n))){e.next=5;break}return e.abrupt("return",o.split(","));case 5:return e.next=7,T(b(t));case 7:return i=e.sent,localStorage.setItem(n,i.join()),e.abrupt("return",i);case 10:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"init",value:function(){var e=this,t=b(arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.level),n=t.trees,o=t.spots,r=t.buckets,i=t.man;this.clear(),n.forEach(function(t){var n=u()(t,2),o=n[0],r=n[1];return e.addItem("tree",o,r)}),o.forEach(function(t){var n=u()(t,2),o=n[0],r=n[1];return e.addItem("spot",o,r)}),r.forEach(function(t){var n=u()(t,2),o=n[0],r=n[1];return e.addItem("bucket",o,r)}),this.addItem.apply(this,["boxman"].concat(d()(i)))}},{key:"autoPlay",value:function(){var e=a()(r.a.mark(function e(t){var n,o,i,a=arguments;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:n=a.length>1&&void 0!==a[1]?a[1]:this.level,this.init(n),o=0;case 3:if(!(oe.MAX_LEVEL)&&(n=1),this[k]=n,this.init(n),this.onload&&this.onload(n);case 4:return t.next=6,this.waitCommand();case 6:if(!(o=t.sent)){t.next=10;break}return t.next=10,this.move(o);case 10:if(!this.isWin()){t.next=4;break}case 11:if(!this.onLevelComplete){t.next=14;break}return t.next=14,this.onLevelComplete(n);case 14:case"end":return t.stop()}},t,this)}));return function(e){return t.apply(this,arguments)}}()},{key:"boxman",get:function(){return this.container.querySelector(".boxman")}},{key:"level",get:function(){return this[k]}}]),e}();function I(e){return new Promise(function(t){setTimeout(t,e)})}v()(S,"ITEM_WIDTH",32),v()(S,"MAX_LEVEL",113),new l.Howl({src:["assets/bgsound.mp3"],loop:!0}).play();var L=new l.Howl({src:["assets/step.mp3"]}),E=new l.Howl({src:["assets/success.mp3"]}),O=document.getElementById("currentlevel"),P=document.getElementById("previouslevel"),M=document.getElementById("nextlevel"),H=document.getElementById("reset"),B=document.getElementById("autoplay"),F=Number(localStorage.getItem("playlevel"))||1,N=new S({container:document.getElementById("boxmap"),onload:function(e){O.value=e},onmove:function(e,t){var n=u()(e,2),o=(n[0],n[1]),r=L;if(o){var i=this.getXY(o),a=u()(i,2),s=a[0],l=a[1];"left"===t?s--:"right"===t?s++:"up"===t?l--:l++,this.getSpot(s,l)&&(r=E)}r.play()},onLevelComplete:function(){var e=a()(r.a.mark(function e(t){var n;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return localStorage.setItem("playlevel",t+1),(n=document.getElementById("game-result")).className="show",e.next=5,I(1300);case 5:return n.className="",e.next=8,I(200);case 8:this.load(t+1);case 9:case"end":return e.stop()}},e,this)}));return function(t){return e.apply(this,arguments)}}()});N.load(F),O.addEventListener("change",function(e){var t=e.target;N.load(Number(t.value))}),P.addEventListener("click",function(){N.load(N.level-1)}),M.addEventListener("click",function(){N.load(N.level+1)}),H.addEventListener("click",function(){N.load(N.level)}),B.addEventListener("click",a()(r.a.mark(function e(){var t;return r.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return B.disabled=!0,B.innerHTML="思考中...",e.next=4,N.solve(N.level);case 4:return t=e.sent,B.innerHTML="行动中...",e.next=8,N.autoPlay(t,N.level);case 8:B.disabled=!1,B.innerHTML="自动过关";case 10:case"end":return e.stop()}},e)}))),window.app=N}])});
--------------------------------------------------------------------------------