├── tmp
└── .gitkeep
├── .npmignore
├── models
├── Model.es6
├── things
│ ├── WallThingModel.es6
│ ├── PlayerThingModel.es6
│ ├── UpstairsThingModel.es6
│ ├── PicksThingModel.es6
│ ├── BonusTime5ThingModel.es6
│ ├── PenaltyTime3ThingModel.es6
│ └── ThingModel.es6
├── GameResultModel.es6
├── ThingIndexerModel.es6
└── CellModel.es6
├── circle.yml
├── doc
├── demo.gif
├── demo-2.gif
└── demo-3.gif
├── test
├── support
│ ├── some-es5-module.js
│ ├── some-es6-module.es6
│ └── helpers.es6
├── mocha.opts
├── conf
│ └── index.es6
├── models
│ ├── GameResultModel.es6
│ ├── things
│ │ ├── WallThingModel.es6
│ │ ├── PlayerThingModel.es6
│ │ └── ThingModel.es6
│ ├── ThingIndexerModel.es6
│ └── CellModel.es6
├── stores
│ ├── ScreenStore.es6
│ ├── Store.es6
│ └── GameStore.es6
├── vendors
│ └── power-assert.es6
├── app.es6
├── input
│ └── AppInput.es6
└── lib
│ ├── stages
│ └── index.es6
│ ├── mixins
│ └── SingletonMixin.es6
│ ├── util.es6
│ └── apis
│ └── index.es6
├── server
└── aws-lambda
│ ├── aws-config.example.json
│ ├── package.json
│ ├── local-runner.js
│ └── index.js
├── consts
├── index.es6
├── keys.es6
├── events.es6
└── actions.es6
├── env
├── development.js
├── test.js
└── production.js
├── dist
├── test
│ ├── support
│ │ ├── some-es6-module.js
│ │ └── helpers.js
│ ├── conf
│ │ └── index.js
│ ├── models
│ │ ├── GameResultModel.js
│ │ ├── ThingIndexerModel.js
│ │ ├── things
│ │ │ ├── WallThingModel.js
│ │ │ ├── PlayerThingModel.js
│ │ │ └── ThingModel.js
│ │ └── CellModel.js
│ ├── stores
│ │ ├── ScreenStore.js
│ │ ├── Store.js
│ │ └── GameStore.js
│ ├── vendors
│ │ └── power-assert.js
│ ├── lib
│ │ ├── stages
│ │ │ └── index.js
│ │ ├── util.js
│ │ ├── mixins
│ │ │ └── SingletonMixin.js
│ │ └── apis
│ │ │ └── index.js
│ ├── app.js
│ └── input
│ │ └── AppInput.js
├── consts
│ ├── index.js
│ ├── keys.js
│ ├── events.js
│ └── actions.js
├── models
│ ├── Model.js
│ ├── things
│ │ ├── WallThingModel.js
│ │ ├── PlayerThingModel.js
│ │ ├── PicksThingModel.js
│ │ ├── UpstairsThingModel.js
│ │ ├── BonusTime5ThingModel.js
│ │ ├── PenaltyTime3ThingModel.js
│ │ └── ThingModel.js
│ ├── GameResultModel.js
│ ├── ThingIndexerModel.js
│ └── CellModel.js
├── components
│ ├── variables.js
│ ├── Screen.js
│ ├── pages
│ │ └── WelcomePageComponent.js
│ └── DialogComponent.js
├── conf
│ └── index.js
├── input
│ ├── subscriptions
│ │ ├── error.js
│ │ ├── timer.js
│ │ └── keypress.js
│ └── AppInput.js
├── lib
│ ├── mixins
│ │ └── SingletonMixin.js
│ ├── EventManager.js
│ ├── stages
│ │ └── index.js
│ ├── util.js
│ └── apis
│ │ └── index.js
├── stores
│ ├── Store.js
│ ├── DialogStore.js
│ └── ScreenStore.js
├── dispatcher
│ └── AppDispatcher.js
├── actions
│ ├── ScreenActionCreators.js
│ └── GameActionCreators.js
└── app.js
├── dispatcher
└── AppDispatcher.es6
├── input
├── subscriptions
│ ├── error.es6
│ ├── timer.es6
│ └── keypress.es6
└── AppInput.es6
├── conf
└── index.es6
├── gulpfile.js
├── components
├── variables.es6
├── pages
│ ├── WelcomePageComponent.es6
│ └── GamePageComponent.es6
├── Screen.es6
├── DialogComponent.es6
└── RootComponent.es6
├── lib
├── EventManager.es6
├── mixins
│ └── SingletonMixin.es6
├── stages
│ └── index.es6
├── util.es6
└── apis
│ └── index.es6
├── stores
├── Store.es6
├── ScreenStore.es6
└── DialogStore.es6
├── .gitignore
├── .eslintrc
├── README.md
├── LICENSE
├── bin
└── escape-from-the-maze
├── actions
├── ScreenActionCreators.es6
└── GameActionCreators.es6
├── app.es6
└── package.json
/tmp/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .envrc
2 | /server
3 |
--------------------------------------------------------------------------------
/models/Model.es6:
--------------------------------------------------------------------------------
1 | export default class Model {
2 | }
3 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | node:
3 | version: "0.12"
4 |
--------------------------------------------------------------------------------
/doc/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kjirou/escape-from-the-maze/HEAD/doc/demo.gif
--------------------------------------------------------------------------------
/test/support/some-es5-module.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | foo: 1,
3 | bar: 2
4 | };
5 |
--------------------------------------------------------------------------------
/test/support/some-es6-module.es6:
--------------------------------------------------------------------------------
1 | export default {
2 | foo: 1,
3 | bar: 2
4 | };
5 |
--------------------------------------------------------------------------------
/doc/demo-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kjirou/escape-from-the-maze/HEAD/doc/demo-2.gif
--------------------------------------------------------------------------------
/doc/demo-3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kjirou/escape-from-the-maze/HEAD/doc/demo-3.gif
--------------------------------------------------------------------------------
/server/aws-lambda/aws-config.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "accessKeyId": "",
3 | "secretAccessKey": ""
4 | }
5 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --compilers es6:espower-babel/guess
2 | --require env/test
3 | --timeout 10000
4 | --recursive
5 |
--------------------------------------------------------------------------------
/consts/index.es6:
--------------------------------------------------------------------------------
1 | export const ACTIONS = require('./actions');
2 | export const EVENTS = require('./events');
3 | export const KEYS = require('./keys');
4 |
--------------------------------------------------------------------------------
/env/development.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = 'development';
2 | process.env.NODE_PATH = __dirname + '/..';
3 | require('module')._initPaths();
4 | require('babel/register');
5 |
--------------------------------------------------------------------------------
/consts/keys.es6:
--------------------------------------------------------------------------------
1 | const KEYS = {
2 | STAGE_SELECTION: {
3 | 'a': 'simple',
4 | 'b': 'easy',
5 | 'c': 'normal',
6 | 'd': 'hard',
7 | 'e': 'lunatic'
8 | }
9 | };
10 |
11 |
12 | export default KEYS;
13 |
--------------------------------------------------------------------------------
/env/test.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = 'test';
2 | process.env.NODE_PATH = __dirname + '/..';
3 | require('module')._initPaths();
4 | require('babel/register');
5 |
6 | var conf = require('conf');
7 | conf.ignoreScreenOutput = true;
8 |
--------------------------------------------------------------------------------
/dist/test/support/some-es6-module.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports["default"] = {
7 | foo: 1,
8 | bar: 2
9 | };
10 | module.exports = exports["default"];
--------------------------------------------------------------------------------
/dispatcher/AppDispatcher.es6:
--------------------------------------------------------------------------------
1 | import {Dispatcher} from 'flux';
2 |
3 | import SingletonMixin from 'lib/mixins/SingletonMixin';
4 |
5 |
6 | export default class AppDispatcher extends Dispatcher {
7 | }
8 |
9 | Object.assign(AppDispatcher, SingletonMixin);
10 |
--------------------------------------------------------------------------------
/input/subscriptions/error.es6:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 |
3 | import ScreenActionCreators from 'actions/ScreenActionCreators';
4 |
5 |
6 | export function onError(err) {
7 | console.error(chalk.red(err));
8 | ScreenActionCreators.throwRuntimeError(err);
9 | }
10 |
--------------------------------------------------------------------------------
/conf/index.es6:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 |
3 |
4 | const conf = {
5 | apiUrl: 'https://94uubrff77.execute-api.us-east-1.amazonaws.com/prod',
6 | fps: 60,
7 | ignoreScreenOutput: false,
8 | root: path.join(__dirname, '/..')
9 | };
10 |
11 |
12 | export default conf;
13 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var gulpBabel = require('gulp-babel');
3 |
4 |
5 | var DIST_DIR = './dist';
6 |
7 |
8 | gulp.task('build', function (){
9 | return gulp.src('**/*.es6')
10 | .pipe(gulpBabel())
11 | .pipe(gulp.dest(DIST_DIR))
12 | ;
13 | });
14 |
--------------------------------------------------------------------------------
/consts/events.es6:
--------------------------------------------------------------------------------
1 | import keymirror from 'keymirror';
2 |
3 |
4 | const EVENTS = keymirror({
5 | CHANGE_PAGE: null,
6 | EXIT: null,
7 | UPDATE_DIALOG: null,
8 | UPDATE_ERRORS: null,
9 | UPDATE_GAME_STATUS: null,
10 | UPDATE_MAZE: null
11 | });
12 |
13 |
14 | export default EVENTS;
15 |
--------------------------------------------------------------------------------
/components/variables.es6:
--------------------------------------------------------------------------------
1 | const variables = {
2 | pageBoxProps: {
3 | top: 'top',
4 | left: 'left',
5 | width: '100%',
6 | height: '100%',
7 | tags: true,
8 | style: {
9 | fg: 'white',
10 | bg: 'black'
11 | }
12 | }
13 | };
14 |
15 |
16 | export default variables;
17 |
--------------------------------------------------------------------------------
/dist/consts/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | var ACTIONS = require('./actions');
7 | exports.ACTIONS = ACTIONS;
8 | var EVENTS = require('./events');
9 | exports.EVENTS = EVENTS;
10 | var KEYS = require('./keys');
11 | exports.KEYS = KEYS;
--------------------------------------------------------------------------------
/server/aws-lambda/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "for-aws-lambda",
3 | "version": "0.0.0",
4 | "description": "For ZIP file creation that is uploaded to AWS Lambda",
5 | "dependencies": {
6 | "async": "1.4.2",
7 | "aws-sdk": "2.1.48",
8 | "lodash": "3.10.1"
9 | },
10 | "private": true
11 | }
12 |
--------------------------------------------------------------------------------
/test/support/helpers.es6:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 |
3 | import conf from 'conf';
4 |
5 |
6 | export function heading(filePath) {
7 | let relativePath = path.relative(conf.root, filePath);
8 | relativePath = relativePath.replace(/^test\//, '');
9 | relativePath = relativePath.replace(/\.es6$/, '');
10 | return relativePath;
11 | }
12 |
--------------------------------------------------------------------------------
/models/things/WallThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class WallThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = '#';
10 | this._isPassable = false;
11 | }
12 | }
13 |
14 | Object.assign(WallThingModel, {
15 | typeId: 'wall'
16 | });
17 |
--------------------------------------------------------------------------------
/dist/consts/keys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | var KEYS = {
7 | STAGE_SELECTION: {
8 | 'a': 'simple',
9 | 'b': 'easy',
10 | 'c': 'normal',
11 | 'd': 'hard',
12 | 'e': 'lunatic'
13 | }
14 | };
15 |
16 | exports['default'] = KEYS;
17 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/test/conf/index.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import path from 'path';
3 |
4 | import conf from 'conf';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('root', function() {
11 | let App = require(path.join(conf.root, 'app.es6'));
12 | assert.strictEqual(typeof App, 'function');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/models/GameResultModel.es6:
--------------------------------------------------------------------------------
1 | import Model from 'models/Model';
2 |
3 |
4 | export default class GameResultModel extends Model {
5 |
6 | constructor({ timeLimit, lastGameTime }) {
7 | super();
8 |
9 | this._timeLimit = timeLimit;
10 | this._lastGameTime = lastGameTime;
11 | }
12 |
13 | calculateScore() {
14 | return this._timeLimit - this._lastGameTime;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/EventManager.es6:
--------------------------------------------------------------------------------
1 | import {EventEmitter} from 'events';
2 |
3 | import SingletonMixin from 'lib/mixins/SingletonMixin';
4 |
5 |
6 | export default class EventManager {
7 |
8 | constructor() {
9 |
10 | this._emitter = new EventEmitter();
11 |
12 | Object.defineProperty(this, 'emitter', { get() { return this._emitter; } });
13 | }
14 | }
15 |
16 | Object.assign(EventManager, SingletonMixin);
17 |
--------------------------------------------------------------------------------
/models/things/PlayerThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class PlayerThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = '@';
10 | }
11 |
12 | toContent() {
13 | return '{magenta-fg}' + this._symbol + '{/}';
14 | }
15 | }
16 |
17 | Object.assign(PlayerThingModel, {
18 | typeId: 'player'
19 | });
20 |
--------------------------------------------------------------------------------
/models/things/UpstairsThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class UpstairsThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = '<';
10 | }
11 |
12 | toContent() {
13 | return '{magenta-fg}' + this._symbol + '{/}';
14 | }
15 | }
16 |
17 | Object.assign(UpstairsThingModel, {
18 | typeId: 'upstairs'
19 | });
20 |
--------------------------------------------------------------------------------
/stores/Store.es6:
--------------------------------------------------------------------------------
1 | import SingletonMixin from 'lib/mixins/SingletonMixin';
2 |
3 |
4 | export default class Store {
5 |
6 | constructor() {
7 | this._dispatchToken = null;
8 | }
9 |
10 | getDispatchToken() {
11 | if (!this._dispatchToken) {
12 | throw new Error('dispatchToken does not exist');
13 | }
14 | return this._dispatchToken;
15 | }
16 | }
17 |
18 | Object.assign(Store, SingletonMixin);
19 |
--------------------------------------------------------------------------------
/dist/models/Model.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8 |
9 | var Model = function Model() {
10 | _classCallCheck(this, Model);
11 | };
12 |
13 | exports["default"] = Model;
14 | module.exports = exports["default"];
--------------------------------------------------------------------------------
/models/things/PicksThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class PicksThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = 'T';
10 | this._isPickable = true;
11 | }
12 |
13 | toContent() {
14 | return '{yellow-fg}' + this._symbol + '{/}';
15 | }
16 | }
17 |
18 | Object.assign(PicksThingModel, {
19 | typeId: 'picks'
20 | });
21 |
--------------------------------------------------------------------------------
/test/models/GameResultModel.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import GameResultModel from 'models/GameResultModel';
4 | import {heading} from 'test/support/helpers';
5 |
6 |
7 | describe(heading(__filename), function() {
8 |
9 | it('calculateScore', function() {
10 | let store = new GameResultModel({ timeLimit: 100000, lastGameTime: 77777 });
11 | assert.strictEqual(store.calculateScore(), 22223);
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/dist/components/variables.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | var variables = {
7 | pageBoxProps: {
8 | top: 'top',
9 | left: 'left',
10 | width: '100%',
11 | height: '100%',
12 | tags: true,
13 | style: {
14 | fg: 'white',
15 | bg: 'black'
16 | }
17 | }
18 | };
19 |
20 | exports['default'] = variables;
21 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/models/things/BonusTime5ThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class BonusTime5ThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = '5';
10 | this._isPickable = true;
11 | }
12 |
13 | toContent() {
14 | return '{green-fg}' + this._symbol + '{/}';
15 | }
16 | }
17 |
18 | Object.assign(BonusTime5ThingModel, {
19 | typeId: 'bonus_time_5'
20 | });
21 |
--------------------------------------------------------------------------------
/models/things/PenaltyTime3ThingModel.es6:
--------------------------------------------------------------------------------
1 | import ThingModel from 'models/things/ThingModel';
2 |
3 |
4 | export default class PenaltyTime3ThingModel extends ThingModel {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._symbol = '3';
10 | this._isPickable = true;
11 | }
12 |
13 | toContent() {
14 | return '{red-fg}' + this._symbol + '{/}';
15 | }
16 | }
17 |
18 | Object.assign(PenaltyTime3ThingModel, {
19 | typeId: 'penalty_time_3'
20 | });
21 |
--------------------------------------------------------------------------------
/env/production.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = 'production';
2 | process.env.NODE_PATH = [
3 | // At first, look for the transpiled code
4 | __dirname + '/../dist',
5 | //__dirname + '/..'
6 | ].join(':');
7 | require('module')._initPaths();
8 | require("babel/polyfill");
9 | // Does not work `require('babel/register');` at installed globally.
10 | // Ref) https://babeljs.io/docs/usage/require/
11 | //require('babel/register')({
12 | // ignore: false,
13 | // extensions: ['.es6']
14 | //});
15 |
--------------------------------------------------------------------------------
/test/stores/ScreenStore.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import ScreenStore from 'stores/ScreenStore';
4 | import {heading} from 'test/support/helpers';
5 |
6 |
7 | describe(heading(__filename), function() {
8 |
9 | it('should be defined', function() {
10 | assert.strictEqual(typeof ScreenStore, 'function');
11 | });
12 |
13 | it('pageId', function() {
14 | var store = new ScreenStore();
15 | store._pageId = 'foo';
16 | assert.strictEqual(store.pageId, 'foo');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.db
2 | *.egg
3 | *.egg-info
4 | *.gem
5 | *.idea
6 | *.log
7 | *.mo
8 | *.orig
9 | *.py[cod]
10 | *.secret
11 | *.sqlite
12 | *.swp
13 | *.tap
14 | *.DS_Store
15 | .bundle
16 | .config
17 | .coverage
18 | .envrc
19 | .installed.cfg
20 | .mr.developer.cfg
21 | .project
22 | .pydevproject
23 | .sqlite3-journal
24 | .svn/
25 | .tox/
26 | bower_components/
27 | develop-eggs/
28 | eggs/
29 | node_modules/
30 | coverage
31 | nosetests.xml
32 | npm-debug.log
33 | pip-log.txt
34 | testem.*.*.*.json
35 |
36 |
37 | /tmp/*.*
38 | aws-config.json
39 |
--------------------------------------------------------------------------------
/lib/mixins/SingletonMixin.es6:
--------------------------------------------------------------------------------
1 | const SingletomMixin = {
2 |
3 | _instance: null,
4 |
5 | getInstance: function getInstance(...args) {
6 | if (this._instance && this._instance instanceof this) {
7 | return this._instance;
8 | }
9 | this._instance = new this(...args);
10 | return this._instance;
11 | },
12 |
13 | clearInstance: function clearInstance() {
14 | if (this._destructInstance) {
15 | this._destructInstance();
16 | }
17 | this._instance = null;
18 | }
19 | };
20 |
21 |
22 | export default SingletomMixin;
23 |
--------------------------------------------------------------------------------
/models/ThingIndexerModel.es6:
--------------------------------------------------------------------------------
1 | import Model from 'models/Model';
2 |
3 |
4 | export default class ThingIndexerModel extends Model {
5 |
6 | constructor() {
7 | super();
8 |
9 | this._indexes = {};
10 | }
11 |
12 | update(id, pos) {
13 | this._indexes[id] = pos;
14 | }
15 |
16 | remove(id) {
17 | delete this._indexes[id];
18 | }
19 |
20 | get(id) {
21 | return this._indexes[id] || null;
22 | }
23 |
24 | has(id) {
25 | return id in this._indexes;
26 | }
27 |
28 | getIds() {
29 | return Object.keys(this._indexes);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/dist/conf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8 |
9 | var _path = require('path');
10 |
11 | var _path2 = _interopRequireDefault(_path);
12 |
13 | var conf = {
14 | apiUrl: 'https://94uubrff77.execute-api.us-east-1.amazonaws.com/prod',
15 | fps: 60,
16 | ignoreScreenOutput: false,
17 | root: _path2['default'].join(__dirname, '/..')
18 | };
19 |
20 | exports['default'] = conf;
21 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/test/stores/Store.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import Store from 'stores/Store';
4 | import {heading} from 'test/support/helpers';
5 |
6 |
7 | describe(heading(__filename), function() {
8 |
9 | it('should be defined', function() {
10 | assert.strictEqual(typeof Store, 'function');
11 | });
12 |
13 | it('should be inherited', function() {
14 | class SubStore extends Store {}
15 |
16 | let store = SubStore.getInstance();
17 | let store2 = SubStore.getInstance();
18 | assert.strictEqual(store, store2, 'Can use inherited static props');
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/dist/consts/events.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8 |
9 | var _keymirror = require('keymirror');
10 |
11 | var _keymirror2 = _interopRequireDefault(_keymirror);
12 |
13 | var EVENTS = (0, _keymirror2['default'])({
14 | CHANGE_PAGE: null,
15 | EXIT: null,
16 | UPDATE_DIALOG: null,
17 | UPDATE_ERRORS: null,
18 | UPDATE_GAME_STATUS: null,
19 | UPDATE_MAZE: null
20 | });
21 |
22 | exports['default'] = EVENTS;
23 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/test/vendors/power-assert.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import someEs5Module from '../support/some-es5-module';
4 | import someEs6Module from '../support/some-es6-module';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should assert .js codes as ES5', function() {
11 | assert.deepEqual(someEs5Module, {
12 | foo: 1,
13 | bar: 2
14 | });
15 | });
16 |
17 | it('should assert .es6 codes as ES6', function() {
18 | assert.deepEqual(someEs6Module, {
19 | foo: 1,
20 | bar: 2
21 | });
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/input/subscriptions/timer.es6:
--------------------------------------------------------------------------------
1 | import GameActionCreators from 'actions/GameActionCreators';
2 | import GameStore from 'stores/GameStore';
3 |
4 |
5 | export function onTimer({ value, interval }) {
6 | let gameStore = GameStore.getInstance();
7 |
8 | if (gameStore.isPlaying()) {
9 | GameActionCreators.forwardGameTimeByFrame();
10 | }
11 |
12 | if (gameStore.didPlayerGetVictoryJustNow()) {
13 | if (gameStore.hasNextMaze()) {
14 | GameActionCreators.advanceToNextMaze();
15 | } else {
16 | GameActionCreators.saveVictory();
17 | }
18 | } else if (gameStore.didPlayerGetDefeatJustNow()) {
19 | GameActionCreators.saveDefeat();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/dist/input/subscriptions/error.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | exports.onError = onError;
7 |
8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
9 |
10 | var _chalk = require('chalk');
11 |
12 | var _chalk2 = _interopRequireDefault(_chalk);
13 |
14 | var _actionsScreenActionCreators = require('actions/ScreenActionCreators');
15 |
16 | var _actionsScreenActionCreators2 = _interopRequireDefault(_actionsScreenActionCreators);
17 |
18 | function onError(err) {
19 | console.error(_chalk2['default'].red(err));
20 | _actionsScreenActionCreators2['default'].throwRuntimeError(err);
21 | }
--------------------------------------------------------------------------------
/consts/actions.es6:
--------------------------------------------------------------------------------
1 | import keymirror from 'keymirror';
2 |
3 |
4 | const ACTIONS = keymirror({
5 | ADVANCE_TO_NEXT_MAZE: null,
6 | ASSUME_PICKS_MODE: null,
7 | CLOSE_DIALOG: null,
8 | CANCEL_PICKS_MODE: null,
9 | CHANGE_PAGE: null,
10 | CRUSH_WALL_BY_PLAYER: null,
11 | DELETE_LAST_INPUT_FROM_DIALOG: null,
12 | EXIT: null,
13 | FORWARD_GAME_TIME_BY_FRAME: null,
14 | INPUT_KEY_TO_DIALOG: null,
15 | OPEN_DIALOG: null,
16 | PREPARE_GAME: null,
17 | REQUEST_ADDING_GAME_RESULT: null,
18 | RESET_GAME: null,
19 | SAVE_DEFEAT: null,
20 | SAVE_VICTORY: null,
21 | SELECT_STAGE: null,
22 | THROW_RUNTIME_ERROR: null,
23 | WALK_PLAYER: null
24 | });
25 |
26 |
27 | export default ACTIONS;
28 |
--------------------------------------------------------------------------------
/dist/test/support/helpers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | exports.heading = heading;
7 |
8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
9 |
10 | var _path = require('path');
11 |
12 | var _path2 = _interopRequireDefault(_path);
13 |
14 | var _conf = require('conf');
15 |
16 | var _conf2 = _interopRequireDefault(_conf);
17 |
18 | function heading(filePath) {
19 | var relativePath = _path2['default'].relative(_conf2['default'].root, filePath);
20 | relativePath = relativePath.replace(/^test\//, '');
21 | relativePath = relativePath.replace(/\.es6$/, '');
22 | return relativePath;
23 | }
--------------------------------------------------------------------------------
/server/aws-lambda/local-runner.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | global.ESCAPE_FROM_THE_MAZE_AWS_LAMBDA_DEBUG = true;
4 |
5 | var awsLambda = require('./index');
6 |
7 |
8 | var eventMock;
9 | if (0) {
10 | eventMock = {
11 | api_mode: 'add_game_result',
12 | name: 'Testuser',
13 | stage: 'simple',
14 | score: ~~(Math.random() * 50000)
15 | };
16 | } else {
17 | eventMock = {
18 | api_mode: 'get_ranking'
19 | };
20 | }
21 |
22 | var contextMock = {
23 | done: function done(err, response) {
24 | if (err) {
25 | console.error(err);
26 | process.exit(1);
27 | }
28 | console.log(response);
29 | process.exit(0);
30 | }
31 | };
32 |
33 |
34 | awsLambda.handler(eventMock, contextMock);
35 |
--------------------------------------------------------------------------------
/models/things/ThingModel.es6:
--------------------------------------------------------------------------------
1 | import uuid from 'uuid';
2 |
3 | import Model from 'models/Model';
4 |
5 |
6 | export default class ThingModel extends Model {
7 |
8 | constructor() {
9 | super();
10 |
11 | this.uuid = uuid.v4();
12 | this._symbol = '?';
13 | this._isPassable = true;
14 | this._isPickable = false;
15 | }
16 |
17 | getTypeId() {
18 | return this.constructor.typeId;
19 | }
20 |
21 | getSymbol() {
22 | return this._symbol;
23 | }
24 |
25 | isPassable() {
26 | return this._isPassable;
27 | }
28 |
29 | isPickable() {
30 | return this._isPickable;
31 | }
32 |
33 | toContent() {
34 | return this._symbol;
35 | }
36 | }
37 |
38 | Object.assign(ThingModel, {
39 | typeId: '_thing'
40 | });
41 |
--------------------------------------------------------------------------------
/dist/test/conf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _path = require('path');
10 |
11 | var _path2 = _interopRequireDefault(_path);
12 |
13 | var _conf = require('conf');
14 |
15 | var _conf2 = _interopRequireDefault(_conf);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | it('root', function () {
22 | var App = require(_path2['default'].join(_conf2['default'].root, 'app.es6'));
23 | _powerAssert2['default'].strictEqual(typeof App, 'function');
24 | });
25 | });
--------------------------------------------------------------------------------
/dist/test/models/GameResultModel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _modelsGameResultModel = require('models/GameResultModel');
10 |
11 | var _modelsGameResultModel2 = _interopRequireDefault(_modelsGameResultModel);
12 |
13 | var _testSupportHelpers = require('test/support/helpers');
14 |
15 | describe((0, _testSupportHelpers.heading)(__filename), function () {
16 |
17 | it('calculateScore', function () {
18 | var store = new _modelsGameResultModel2['default']({ timeLimit: 100000, lastGameTime: 77777 });
19 | _powerAssert2['default'].strictEqual(store.calculateScore(), 22223);
20 | });
21 | });
--------------------------------------------------------------------------------
/test/app.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import App from 'app';
4 | import EventManager from 'lib/EventManager';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | beforeEach(function() {
11 | App.purgeInstances();
12 | });
13 |
14 | it('should create instance', function() {
15 | let app = new App();
16 | assert.strictEqual(typeof app, 'object');
17 | assert.strictEqual(app instanceof App, true);
18 | });
19 |
20 | it('purgeInstances', function() {
21 | assert.strictEqual(EventManager._instance, null);
22 | EventManager.getInstance();
23 | assert.strictEqual(EventManager._instance instanceof EventManager, true);
24 | App.purgeInstances();
25 | assert.strictEqual(EventManager._instance, null);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "modules": true
4 | },
5 | "rules": {
6 | "linebreak-style": [
7 | 2,
8 | "unix"
9 | ],
10 | "no-console": 0,
11 | "no-unused-vars": [
12 | 2,
13 | {
14 | "args": "none"
15 | }
16 | ],
17 | "quotes": [
18 | 2,
19 | "single"
20 | ],
21 | "semi": [
22 | 2,
23 | "always"
24 | ]
25 | },
26 | "env": {
27 | "es6": true,
28 | "node": true
29 | },
30 | "extends": "eslint:recommended",
31 | "globals": {
32 | "after": true,
33 | "afterEach": true,
34 | "before": true,
35 | "beforeEach": true,
36 | "context": true,
37 | "describe": true,
38 | "it": true
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dist/lib/mixins/SingletonMixin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var _bind = Function.prototype.bind;
7 | var SingletomMixin = {
8 |
9 | _instance: null,
10 |
11 | getInstance: function getInstance() {
12 | if (this._instance && this._instance instanceof this) {
13 | return this._instance;
14 | }
15 |
16 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
17 | args[_key] = arguments[_key];
18 | }
19 |
20 | this._instance = new (_bind.apply(this, [null].concat(args)))();
21 | return this._instance;
22 | },
23 |
24 | clearInstance: function clearInstance() {
25 | if (this._destructInstance) {
26 | this._destructInstance();
27 | }
28 | this._instance = null;
29 | }
30 | };
31 |
32 | exports["default"] = SingletomMixin;
33 | module.exports = exports["default"];
--------------------------------------------------------------------------------
/dist/test/stores/ScreenStore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _storesScreenStore = require('stores/ScreenStore');
10 |
11 | var _storesScreenStore2 = _interopRequireDefault(_storesScreenStore);
12 |
13 | var _testSupportHelpers = require('test/support/helpers');
14 |
15 | describe((0, _testSupportHelpers.heading)(__filename), function () {
16 |
17 | it('should be defined', function () {
18 | _powerAssert2['default'].strictEqual(typeof _storesScreenStore2['default'], 'function');
19 | });
20 |
21 | it('pageId', function () {
22 | var store = new _storesScreenStore2['default']();
23 | store._pageId = 'foo';
24 | _powerAssert2['default'].strictEqual(store.pageId, 'foo');
25 | });
26 | });
--------------------------------------------------------------------------------
/test/input/AppInput.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import sinon from 'sinon';
3 |
4 | import App from 'app';
5 | import AppInput from 'input/AppInput';
6 | import {heading} from 'test/support/helpers';
7 |
8 |
9 | describe(heading(__filename), function() {
10 |
11 | beforeEach(function() {
12 | App.purgeInstances();
13 | });
14 |
15 | it('should create instance', function() {
16 | var input = new AppInput();
17 | assert(input instanceof AppInput);
18 | });
19 |
20 | it('should destruct all observable sequences at clearInstance', function() {
21 | var input = AppInput.getInstance();
22 | var spies = [];
23 | spies.push(sinon.spy(input._timerSubscription, 'dispose'));
24 | spies.push(sinon.spy(input._keypressSubscription, 'dispose'));
25 | AppInput.clearInstance();
26 | assert.strictEqual(spies[0].callCount, 1);
27 | assert.strictEqual(spies[1].callCount, 1);
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/test/lib/stages/index.es6:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import assert from 'power-assert';
3 |
4 | import {
5 | Stage,
6 | stageList,
7 | stages
8 | } from 'lib/stages';
9 | import {heading} from 'test/support/helpers';
10 |
11 |
12 | describe(heading(__filename), function() {
13 |
14 | context('Stage', function() {
15 |
16 | it('getName', function() {
17 | const FooBarStage = Object.assign({}, Stage, {
18 | typeId: 'foo_bar'
19 | });
20 | assert.strictEqual(FooBarStage.getName(), 'Foo Bar');
21 | });
22 | });
23 |
24 | context('stageList, stages', function() {
25 |
26 | it('should be', function() {
27 | assert(stageList.length > 0);
28 | assert.strictEqual(stageList.length, Object.keys(stages).length);
29 |
30 | let descriptions = stageList.map(v => v.description);
31 | assert.strictEqual(descriptions.length, _.unique(descriptions).length);
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/test/lib/mixins/SingletonMixin.es6:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import assert from 'power-assert';
3 |
4 | import SingletonMixin from 'lib/mixins/SingletonMixin';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should be defined', function() {
11 | assert.strictEqual(typeof SingletonMixin, 'object');
12 | });
13 |
14 | it('getInstance, clearInstance', () => {
15 | class Foo {
16 | constructor(x, y) {
17 | this.data = {
18 | x: x,
19 | y: y
20 | };
21 | }
22 | }
23 | _.assign(Foo, SingletonMixin);
24 |
25 | let foo = Foo.getInstance(1, 2);
26 | assert.deepEqual(foo.data, { x: 1, y: 2 });
27 | let foo2 = Foo.getInstance();
28 | assert(foo === foo2);
29 |
30 | Foo.clearInstance();
31 | let foo3 = Foo.getInstance(2, 3);
32 | assert(foo !== foo3);
33 | assert.deepEqual(foo3.data, { x: 2, y: 3 });
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # escape-from-the-maze
2 |
3 | [](http://badge.fury.io/js/escape-from-the-maze)
4 | [](https://circleci.com/gh/kjirou/escape-from-the-maze)
5 |
6 | A simple & tiny CUI maze game
7 |
8 | 
9 |
10 |
11 | ## Installation
12 |
13 | ```bash
14 | npm install -g escape-from-the-maze
15 | ```
16 |
17 |
18 | ## Usage
19 |
20 | Start game:
21 |
22 | ```bash
23 | escape-from-the-maze
24 | ```
25 |
26 | Show ranking:
27 |
28 | ```bash
29 | escape-from-the-maze --ranking
30 | escape-from-the-maze -r
31 | ```
32 |
33 | Show help:
34 |
35 | ```bash
36 | escape-from-the-maze --help
37 | escape-from-the-maze -h
38 | ```
39 |
40 |
41 | ## Development
42 |
43 | ```bash
44 | git clone git@github.com:kjirou/escape-from-the-maze.git
45 | cd ./escape-from-the-maze
46 | npm install
47 | npm start
48 | ```
49 |
--------------------------------------------------------------------------------
/dist/lib/EventManager.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
10 |
11 | var _events = require('events');
12 |
13 | var _libMixinsSingletonMixin = require('lib/mixins/SingletonMixin');
14 |
15 | var _libMixinsSingletonMixin2 = _interopRequireDefault(_libMixinsSingletonMixin);
16 |
17 | var EventManager = function EventManager() {
18 | _classCallCheck(this, EventManager);
19 |
20 | this._emitter = new _events.EventEmitter();
21 |
22 | Object.defineProperty(this, 'emitter', { get: function get() {
23 | return this._emitter;
24 | } });
25 | };
26 |
27 | exports['default'] = EventManager;
28 |
29 | Object.assign(EventManager, _libMixinsSingletonMixin2['default']);
30 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/dist/consts/actions.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8 |
9 | var _keymirror = require('keymirror');
10 |
11 | var _keymirror2 = _interopRequireDefault(_keymirror);
12 |
13 | var ACTIONS = (0, _keymirror2['default'])({
14 | ADVANCE_TO_NEXT_MAZE: null,
15 | ASSUME_PICKS_MODE: null,
16 | CLOSE_DIALOG: null,
17 | CANCEL_PICKS_MODE: null,
18 | CHANGE_PAGE: null,
19 | CRUSH_WALL_BY_PLAYER: null,
20 | DELETE_LAST_INPUT_FROM_DIALOG: null,
21 | EXIT: null,
22 | FORWARD_GAME_TIME_BY_FRAME: null,
23 | INPUT_KEY_TO_DIALOG: null,
24 | OPEN_DIALOG: null,
25 | PREPARE_GAME: null,
26 | REQUEST_ADDING_GAME_RESULT: null,
27 | RESET_GAME: null,
28 | SAVE_DEFEAT: null,
29 | SAVE_VICTORY: null,
30 | SELECT_STAGE: null,
31 | THROW_RUNTIME_ERROR: null,
32 | WALK_PLAYER: null
33 | });
34 |
35 | exports['default'] = ACTIONS;
36 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/dist/test/vendors/power-assert.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _supportSomeEs5Module = require('../support/some-es5-module');
10 |
11 | var _supportSomeEs5Module2 = _interopRequireDefault(_supportSomeEs5Module);
12 |
13 | var _supportSomeEs6Module = require('../support/some-es6-module');
14 |
15 | var _supportSomeEs6Module2 = _interopRequireDefault(_supportSomeEs6Module);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | it('should assert .js codes as ES5', function () {
22 | _powerAssert2['default'].deepEqual(_supportSomeEs5Module2['default'], {
23 | foo: 1,
24 | bar: 2
25 | });
26 | });
27 |
28 | it('should assert .es6 codes as ES6', function () {
29 | _powerAssert2['default'].deepEqual(_supportSomeEs6Module2['default'], {
30 | foo: 1,
31 | bar: 2
32 | });
33 | });
34 | });
--------------------------------------------------------------------------------
/test/models/things/WallThingModel.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import validatorjs from 'validator';
3 |
4 | import WallThingModel from 'models/things/WallThingModel';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should be defined', function() {
11 | assert.strictEqual(typeof WallThingModel, 'function');
12 | });
13 |
14 | it('uuid', function() {
15 | let thing = new WallThingModel();
16 | assert(validatorjs.isUUID(thing.uuid, 4));
17 | });
18 |
19 | it('getTypeId', function() {
20 | let thing = new WallThingModel();
21 | assert.strictEqual(thing.getTypeId(), 'wall');
22 | });
23 |
24 | it('getSymbol', function() {
25 | let thing = new WallThingModel();
26 | assert.strictEqual(thing.getSymbol(), '#');
27 | });
28 |
29 | it('isPassable', function() {
30 | let thing = new WallThingModel();
31 | assert.strictEqual(thing.isPassable(), false);
32 | });
33 |
34 | it('toContent', function() {
35 | let thing = new WallThingModel();
36 | assert.strictEqual(thing.toContent(), '#');
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Koujirou Ishii
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/test/models/things/PlayerThingModel.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import validatorjs from 'validator';
3 |
4 | import PlayerThingModel from 'models/things/PlayerThingModel';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should be defined', function() {
11 | assert.strictEqual(typeof PlayerThingModel, 'function');
12 | });
13 |
14 | it('uuid', function() {
15 | let thing = new PlayerThingModel();
16 | assert(validatorjs.isUUID(thing.uuid, 4));
17 | });
18 |
19 | it('getTypeId', function() {
20 | let thing = new PlayerThingModel();
21 | assert.strictEqual(thing.getTypeId(), 'player');
22 | });
23 |
24 | it('getSymbol', function() {
25 | let thing = new PlayerThingModel();
26 | assert.strictEqual(thing.getSymbol(), '@');
27 | });
28 |
29 | it('isPassable', function() {
30 | let thing = new PlayerThingModel();
31 | assert.strictEqual(thing.isPassable(), true);
32 | });
33 |
34 | it('toContent', function() {
35 | let thing = new PlayerThingModel();
36 | assert.strictEqual(thing.toContent(), '{magenta-fg}@{/}');
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/bin/escape-from-the-maze:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var minimist = require('minimist');
4 |
5 | var commandOptions = minimist(process.argv.slice(2), {
6 | default: {
7 | development: false,
8 | help: false,
9 | ranking: false,
10 | version: false
11 | },
12 | alias: {
13 | development: ['d'],
14 | help: ['h'],
15 | ranking: ['r'],
16 | version: ['v']
17 | }
18 | });
19 |
20 | if (commandOptions.development) {
21 | require('../env/development');
22 | } else {
23 | require('../env/production');
24 | }
25 |
26 | var pkg = require('../package.json');
27 | var App = require('app');
28 | var apis = require('lib/apis');
29 | var libUtil = require('lib/util');
30 |
31 |
32 | if (commandOptions.help) {
33 | console.log(libUtil.createHelpText());
34 | process.exit(0);
35 | } else if (commandOptions.version) {
36 | console.log(pkg.version);
37 | process.exit(0);
38 | } else if (commandOptions.ranking) {
39 | apis.requestRanking(function(err, text) {
40 | if (err) {
41 | console.error(err);
42 | return process.exit(1);
43 | }
44 | console.log(text);
45 | process.exit(0);
46 | });
47 | } else {
48 | var app = App.getInstance();
49 | app.start();
50 | }
51 |
--------------------------------------------------------------------------------
/test/models/ThingIndexerModel.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import uuidModule from 'uuid';
3 |
4 | import ThingIndexerModel from 'models/ThingIndexerModel';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should be defined', function() {
11 | assert.strictEqual(typeof ThingIndexerModel, 'function');
12 | });
13 |
14 | it('update, get, getIds', function() {
15 | let indexer = new ThingIndexerModel();
16 | assert.deepEqual(indexer.getIds(), []);
17 | let uuid = uuidModule.v4();
18 | indexer.update(uuid, [1, 2]);
19 | indexer.update(uuid, [1, 3]);
20 | assert.deepEqual(indexer.get(uuid), [1, 3]);
21 | assert.deepEqual(indexer.getIds(), [uuid]);
22 | assert.strictEqual(indexer.get('not-existing-uuid'), null);
23 | });
24 |
25 | it('remove', function() {
26 | let indexer = new ThingIndexerModel();
27 | let uuid1 = uuidModule.v4();
28 | let uuid2 = uuidModule.v4();
29 | indexer.update(uuid1, [1, 2]);
30 | indexer.update(uuid2, [1, 3]);
31 | assert.deepEqual(indexer.get(uuid1), [1, 2]);
32 | indexer.remove(uuid1);
33 | assert.strictEqual(indexer.get(uuid1), null);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/dist/input/subscriptions/timer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 | exports.onTimer = onTimer;
7 |
8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
9 |
10 | var _actionsGameActionCreators = require('actions/GameActionCreators');
11 |
12 | var _actionsGameActionCreators2 = _interopRequireDefault(_actionsGameActionCreators);
13 |
14 | var _storesGameStore = require('stores/GameStore');
15 |
16 | var _storesGameStore2 = _interopRequireDefault(_storesGameStore);
17 |
18 | function onTimer(_ref) {
19 | var value = _ref.value;
20 | var interval = _ref.interval;
21 |
22 | var gameStore = _storesGameStore2['default'].getInstance();
23 |
24 | if (gameStore.isPlaying()) {
25 | _actionsGameActionCreators2['default'].forwardGameTimeByFrame();
26 | }
27 |
28 | if (gameStore.didPlayerGetVictoryJustNow()) {
29 | if (gameStore.hasNextMaze()) {
30 | _actionsGameActionCreators2['default'].advanceToNextMaze();
31 | } else {
32 | _actionsGameActionCreators2['default'].saveVictory();
33 | }
34 | } else if (gameStore.didPlayerGetDefeatJustNow()) {
35 | _actionsGameActionCreators2['default'].saveDefeat();
36 | }
37 | }
--------------------------------------------------------------------------------
/test/lib/util.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 |
3 | import conf from 'conf';
4 | import {
5 | calculateMillisecondsPerFrame,
6 | createCounter,
7 | createHelpText,
8 | dictionarize
9 | } from 'lib/util';
10 | import {heading} from 'test/support/helpers';
11 |
12 |
13 | describe(heading(__filename), function() {
14 |
15 | it('createCounter', function() {
16 | let counter;
17 | counter = createCounter();
18 | assert.strictEqual(counter(), 1);
19 | assert.strictEqual(counter(), 2);
20 | counter = createCounter(-2);
21 | assert.strictEqual(counter(), -2);
22 | assert.strictEqual(counter(), -1);
23 | });
24 |
25 | it('calculateMillisecondsPerFrame', function() {
26 | assert.strictEqual(calculateMillisecondsPerFrame(), ~~(1000 / conf.fps));
27 | });
28 |
29 | it('dictionarize', function() {
30 | assert.deepEqual(
31 | dictionarize([
32 | { type: 'foo', value: 1 },
33 | { type: 'bar', value: 2 }
34 | ], 'type'),
35 | {
36 | foo: { type: 'foo', value: 1 },
37 | bar: { type: 'bar', value: 2 }
38 | }
39 | );
40 | });
41 |
42 | it('createHelpText', function() {
43 | assert.strictEqual(typeof createHelpText(), 'string');
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/test/models/things/ThingModel.es6:
--------------------------------------------------------------------------------
1 | import assert from 'power-assert';
2 | import validatorjs from 'validator';
3 |
4 | import ThingModel from 'models/things/ThingModel';
5 | import {heading} from 'test/support/helpers';
6 |
7 |
8 | describe(heading(__filename), function() {
9 |
10 | it('should be defined', function() {
11 | assert.strictEqual(typeof ThingModel, 'function');
12 | });
13 |
14 | it('uuid', function() {
15 | let thingModel = new ThingModel();
16 | assert(validatorjs.isUUID(thingModel.uuid, 4));
17 | });
18 |
19 | it('getTypeId', function() {
20 | let thingModel = new ThingModel();
21 | assert.strictEqual(thingModel.getTypeId(), '_thing');
22 | });
23 |
24 | it('getSymbol', function() {
25 | let thingModel = new ThingModel();
26 | assert.strictEqual(thingModel.getSymbol(), '?');
27 | });
28 |
29 | it('isPassable', function() {
30 | let thingModel = new ThingModel();
31 | assert.strictEqual(thingModel.isPassable(), true);
32 | thingModel._isPassable = false;
33 | assert.strictEqual(thingModel.isPassable(), false);
34 | });
35 |
36 | it('toContent', function() {
37 | let thingModel = new ThingModel();
38 | assert.strictEqual(thingModel.toContent(), thingModel.getSymbol());
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/components/pages/WelcomePageComponent.es6:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React, {Component} from 'react';
3 |
4 | import variables from '../variables';
5 | import {KEYS} from 'consts';
6 | import {stageList} from 'lib/stages';
7 |
8 |
9 | export default class WelcomePageComponent extends Component {
10 |
11 | render() {
12 |
13 | let content = '';
14 |
15 | // Title
16 | content += '{magenta-fg}Escape From The Maze{/}\n\n';
17 |
18 | // Overview
19 | content += 'The purpose of the game is to escape from the maze by operating the "{magenta-fg}@{/}" ';
20 | content += 'by [{green-fg}wasd{/}] [{green-fg}hjkl{/}] or {green-fg}arrow keys{/}. ';
21 | content += 'Futher, by using [{green-fg}space{/}], you can also break the wall by consuming a pickaxe.\n';
22 | content += '{yellow-fg}--help{/} option shows more helps!\n\n';
23 |
24 | // Choices of stages
25 | let invertedKeys = _.invert(KEYS.STAGE_SELECTION);
26 | content += 'Push a {green-fg}key{/} for stage selection.\n\n';
27 | content += stageList.map((Stage) => {
28 | return `[{green-fg}${invertedKeys[Stage.typeId]}{/}] ${Stage.getName()}: ${Stage.description}`;
29 | }).join('\n');
30 |
31 | let props = Object.assign({}, variables.pageBoxProps);
32 |
33 | return (
34 |
35 | {content}
36 |
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/dist/test/lib/stages/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _lodash = require('lodash');
6 |
7 | var _lodash2 = _interopRequireDefault(_lodash);
8 |
9 | var _powerAssert = require('power-assert');
10 |
11 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
12 |
13 | var _libStages = require('lib/stages');
14 |
15 | var _testSupportHelpers = require('test/support/helpers');
16 |
17 | describe((0, _testSupportHelpers.heading)(__filename), function () {
18 |
19 | context('Stage', function () {
20 |
21 | it('getName', function () {
22 | var FooBarStage = Object.assign({}, _libStages.Stage, {
23 | typeId: 'foo_bar'
24 | });
25 | _powerAssert2['default'].strictEqual(FooBarStage.getName(), 'Foo Bar');
26 | });
27 | });
28 |
29 | context('stageList, stages', function () {
30 |
31 | it('should be', function () {
32 | (0, _powerAssert2['default'])(_libStages.stageList.length > 0);
33 | _powerAssert2['default'].strictEqual(_libStages.stageList.length, Object.keys(_libStages.stages).length);
34 |
35 | var descriptions = _libStages.stageList.map(function (v) {
36 | return v.description;
37 | });
38 | _powerAssert2['default'].strictEqual(descriptions.length, _lodash2['default'].unique(descriptions).length);
39 | });
40 | });
41 | });
--------------------------------------------------------------------------------
/dist/test/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _app = require('app');
10 |
11 | var _app2 = _interopRequireDefault(_app);
12 |
13 | var _libEventManager = require('lib/EventManager');
14 |
15 | var _libEventManager2 = _interopRequireDefault(_libEventManager);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | beforeEach(function () {
22 | _app2['default'].purgeInstances();
23 | });
24 |
25 | it('should create instance', function () {
26 | var app = new _app2['default']();
27 | _powerAssert2['default'].strictEqual(typeof app, 'object');
28 | _powerAssert2['default'].strictEqual(app instanceof _app2['default'], true);
29 | });
30 |
31 | it('purgeInstances', function () {
32 | _powerAssert2['default'].strictEqual(_libEventManager2['default']._instance, null);
33 | _libEventManager2['default'].getInstance();
34 | _powerAssert2['default'].strictEqual(_libEventManager2['default']._instance instanceof _libEventManager2['default'], true);
35 | _app2['default'].purgeInstances();
36 | _powerAssert2['default'].strictEqual(_libEventManager2['default']._instance, null);
37 | });
38 | });
--------------------------------------------------------------------------------
/actions/ScreenActionCreators.es6:
--------------------------------------------------------------------------------
1 | import ACTIONS from 'consts/actions';
2 | import AppDispatcher from 'dispatcher/AppDispatcher';
3 |
4 |
5 | const ScreenActionCreators = {
6 |
7 | changePage(pageId) {
8 | AppDispatcher.getInstance().dispatch({
9 | type: ACTIONS.CHANGE_PAGE,
10 | pageId
11 | });
12 | },
13 |
14 | closeDialog() {
15 | AppDispatcher.getInstance().dispatch({
16 | type: ACTIONS.CLOSE_DIALOG
17 | });
18 | },
19 |
20 | deleteLastInputFromDialog() {
21 | AppDispatcher.getInstance().dispatch({
22 | type: ACTIONS.DELETE_LAST_INPUT_FROM_DIALOG
23 | });
24 | },
25 |
26 | exit() {
27 | AppDispatcher.getInstance().dispatch({
28 | type: ACTIONS.EXIT
29 | });
30 | },
31 |
32 | inputKeyToDialog(keyName) {
33 | AppDispatcher.getInstance().dispatch({
34 | type: ACTIONS.INPUT_KEY_TO_DIALOG,
35 | keyName
36 | });
37 | },
38 |
39 | openDialog() {
40 | AppDispatcher.getInstance().dispatch({
41 | type: ACTIONS.OPEN_DIALOG
42 | });
43 | },
44 |
45 | prepareGame(stageTypeId) {
46 | AppDispatcher.getInstance().dispatch({
47 | type: ACTIONS.PREPARE_GAME,
48 | stageTypeId
49 | });
50 | },
51 |
52 | /*
53 | * @param err {Error}
54 | */
55 | throwRuntimeError(err) {
56 | AppDispatcher.getInstance().dispatch({
57 | type: ACTIONS.THROW_RUNTIME_ERROR,
58 | err
59 | });
60 | }
61 | };
62 |
63 |
64 | export default ScreenActionCreators;
65 |
--------------------------------------------------------------------------------
/components/Screen.es6:
--------------------------------------------------------------------------------
1 | import blessed from 'blessed';
2 | import chalk from 'chalk';
3 | import devnull from 'dev-null';
4 | import _ from 'lodash';
5 | import React from 'react';
6 | import {render} from 'react-blessed';
7 |
8 | import RootComponent from './RootComponent';
9 | import conf from 'conf';
10 | import {EVENTS} from 'consts';
11 | import EventManager from 'lib/EventManager';
12 | import SingletonMixin from 'lib/mixins/SingletonMixin';
13 | import ScreenStore from 'stores/ScreenStore';
14 |
15 |
16 | export default class Screen {
17 |
18 | constructor() {
19 |
20 | let screen = blessed.screen(this._createBlessedOptions());
21 | screen.debugLog.unkey(['q', 'escape']);
22 | render(, screen);
23 | this._screen = screen;
24 |
25 | let {emitter} = EventManager.getInstance();
26 | emitter.on(EVENTS.UPDATE_ERRORS, this._debug.bind(this));
27 | emitter.on(EVENTS.EXIT, this._exit.bind(this));
28 | }
29 |
30 | _createBlessedOptions() {
31 | let options = {
32 | debug: true,
33 | title: 'Escape From The Maze'
34 | };
35 |
36 | if (conf.ignoreScreenOutput) {
37 | options.output = devnull();
38 | }
39 |
40 | return options;
41 | }
42 |
43 | _exit() {
44 | process.stdin.pause();
45 | process.exit(0);
46 | }
47 |
48 | _debug() {
49 | let screenStore = ScreenStore.getInstance();
50 | var err = screenStore.getLastRuntimeError();
51 | this._screen.debug(chalk.red(err));
52 | }
53 | }
54 |
55 | Object.assign(Screen, SingletonMixin);
56 |
--------------------------------------------------------------------------------
/dist/test/input/AppInput.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _sinon = require('sinon');
10 |
11 | var _sinon2 = _interopRequireDefault(_sinon);
12 |
13 | var _app = require('app');
14 |
15 | var _app2 = _interopRequireDefault(_app);
16 |
17 | var _inputAppInput = require('input/AppInput');
18 |
19 | var _inputAppInput2 = _interopRequireDefault(_inputAppInput);
20 |
21 | var _testSupportHelpers = require('test/support/helpers');
22 |
23 | describe((0, _testSupportHelpers.heading)(__filename), function () {
24 |
25 | beforeEach(function () {
26 | _app2['default'].purgeInstances();
27 | });
28 |
29 | it('should create instance', function () {
30 | var input = new _inputAppInput2['default']();
31 | (0, _powerAssert2['default'])(input instanceof _inputAppInput2['default']);
32 | });
33 |
34 | it('should destruct all observable sequences at clearInstance', function () {
35 | var input = _inputAppInput2['default'].getInstance();
36 | var spies = [];
37 | spies.push(_sinon2['default'].spy(input._timerSubscription, 'dispose'));
38 | spies.push(_sinon2['default'].spy(input._keypressSubscription, 'dispose'));
39 | _inputAppInput2['default'].clearInstance();
40 | _powerAssert2['default'].strictEqual(spies[0].callCount, 1);
41 | _powerAssert2['default'].strictEqual(spies[1].callCount, 1);
42 | });
43 | });
--------------------------------------------------------------------------------
/dist/test/lib/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _conf = require('conf');
10 |
11 | var _conf2 = _interopRequireDefault(_conf);
12 |
13 | var _libUtil = require('lib/util');
14 |
15 | var _testSupportHelpers = require('test/support/helpers');
16 |
17 | describe((0, _testSupportHelpers.heading)(__filename), function () {
18 |
19 | it('createCounter', function () {
20 | var counter = undefined;
21 | counter = (0, _libUtil.createCounter)();
22 | _powerAssert2['default'].strictEqual(counter(), 1);
23 | _powerAssert2['default'].strictEqual(counter(), 2);
24 | counter = (0, _libUtil.createCounter)(-2);
25 | _powerAssert2['default'].strictEqual(counter(), -2);
26 | _powerAssert2['default'].strictEqual(counter(), -1);
27 | });
28 |
29 | it('calculateMillisecondsPerFrame', function () {
30 | _powerAssert2['default'].strictEqual((0, _libUtil.calculateMillisecondsPerFrame)(), ~ ~(1000 / _conf2['default'].fps));
31 | });
32 |
33 | it('dictionarize', function () {
34 | _powerAssert2['default'].deepEqual((0, _libUtil.dictionarize)([{ type: 'foo', value: 1 }, { type: 'bar', value: 2 }], 'type'), {
35 | foo: { type: 'foo', value: 1 },
36 | bar: { type: 'bar', value: 2 }
37 | });
38 | });
39 |
40 | it('createHelpText', function () {
41 | _powerAssert2['default'].strictEqual(typeof (0, _libUtil.createHelpText)(), 'string');
42 | });
43 | });
--------------------------------------------------------------------------------
/stores/ScreenStore.es6:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | import {ACTIONS, EVENTS} from 'consts';
4 | import AppDispatcher from 'dispatcher/AppDispatcher';
5 | import EventManager from 'lib/EventManager';
6 | import GameStore from 'stores/GameStore';
7 | import Store from 'stores/Store';
8 |
9 |
10 | const DIALOG_INPUT_MATCHER = /^[a-zA-Z0-9]{1,12}$/;
11 | function validateDialogInput(input) {
12 | return DIALOG_INPUT_MATCHER.test(input);
13 | }
14 |
15 |
16 | class ScreenStore extends Store {
17 |
18 | constructor() {
19 | super();
20 |
21 | this._pageId = 'welcome';
22 | this._runtimeErrors = [];
23 |
24 | Object.defineProperty(this, 'pageId', { get() { return this._pageId; } });
25 |
26 | let dispatcher = AppDispatcher.getInstance();
27 | let {emitter} = EventManager.getInstance();
28 | let gameStore = GameStore.getInstance();
29 | this._dispatchToken = dispatcher.register((action) => {
30 | dispatcher.waitFor([
31 | gameStore.getDispatchToken()
32 | ]);
33 |
34 | switch (action.type) {
35 | case ACTIONS.CHANGE_PAGE:
36 | this._pageId = action.pageId;
37 | emitter.emit(EVENTS.CHANGE_PAGE);
38 | break;
39 | case ACTIONS.EXIT:
40 | emitter.emit(EVENTS.EXIT);
41 | break;
42 | case ACTIONS.THROW_RUNTIME_ERROR:
43 | this._runtimeErrors.push(action.err);
44 | emitter.emit(EVENTS.UPDATE_ERRORS);
45 | break;
46 | }
47 | });
48 | }
49 |
50 | getLastRuntimeError() {
51 | return _.last(this._runtimeErrors);
52 | }
53 | }
54 |
55 |
56 | export default ScreenStore;
57 |
--------------------------------------------------------------------------------
/app.es6:
--------------------------------------------------------------------------------
1 | import ScreenActionCreators from 'actions/ScreenActionCreators';
2 | import Screen from 'components/Screen';
3 | import conf from 'conf';
4 | import AppDispatcher from 'dispatcher/AppDispatcher';
5 | import AppInput from 'input/AppInput';
6 | import EventManager from 'lib/EventManager';
7 | import SingletonMixin from 'lib/mixins/SingletonMixin';
8 | import DialogStore from 'stores/DialogStore';
9 | import GameStore from 'stores/GameStore';
10 | import ScreenStore from 'stores/ScreenStore';
11 |
12 |
13 | export default class App {
14 |
15 | /*
16 | * Initialize unique instances in consideration of the order
17 | */
18 | static initializeInstances() {
19 | [
20 | () => EventManager.getInstance(),
21 | () => AppDispatcher.getInstance(),
22 | () => DialogStore.getInstance(),
23 | () => GameStore.getInstance(),
24 | () => ScreenStore.getInstance(),
25 | () => AppInput.getInstance()
26 | ].forEach(task => task());
27 | }
28 |
29 | static purgeInstances() {
30 | [
31 | () => Screen.clearInstance(),
32 | () => AppInput.clearInstance(),
33 | () => ScreenStore.clearInstance(),
34 | () => DialogStore.clearInstance(),
35 | () => GameStore.clearInstance(),
36 | () => AppDispatcher.clearInstance(),
37 | () => EventManager.clearInstance()
38 | ].forEach(task => task());
39 | }
40 |
41 | constructor() {
42 | this.constructor.initializeInstances();
43 | }
44 |
45 | start() {
46 | Screen.getInstance({ componentMode: conf.componentMode });
47 | ScreenActionCreators.changePage('welcome');
48 | }
49 | }
50 |
51 | Object.assign(App, SingletonMixin);
52 |
--------------------------------------------------------------------------------
/dist/stores/Store.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | var _libMixinsSingletonMixin = require('lib/mixins/SingletonMixin');
14 |
15 | var _libMixinsSingletonMixin2 = _interopRequireDefault(_libMixinsSingletonMixin);
16 |
17 | var Store = (function () {
18 | function Store() {
19 | _classCallCheck(this, Store);
20 |
21 | this._dispatchToken = null;
22 | }
23 |
24 | _createClass(Store, [{
25 | key: 'getDispatchToken',
26 | value: function getDispatchToken() {
27 | if (!this._dispatchToken) {
28 | throw new Error('dispatchToken does not exist');
29 | }
30 | return this._dispatchToken;
31 | }
32 | }]);
33 |
34 | return Store;
35 | })();
36 |
37 | exports['default'] = Store;
38 |
39 | Object.assign(Store, _libMixinsSingletonMixin2['default']);
40 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/dist/test/lib/mixins/SingletonMixin.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6 |
7 | var _lodash = require('lodash');
8 |
9 | var _lodash2 = _interopRequireDefault(_lodash);
10 |
11 | var _powerAssert = require('power-assert');
12 |
13 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
14 |
15 | var _libMixinsSingletonMixin = require('lib/mixins/SingletonMixin');
16 |
17 | var _libMixinsSingletonMixin2 = _interopRequireDefault(_libMixinsSingletonMixin);
18 |
19 | var _testSupportHelpers = require('test/support/helpers');
20 |
21 | describe((0, _testSupportHelpers.heading)(__filename), function () {
22 |
23 | it('should be defined', function () {
24 | _powerAssert2['default'].strictEqual(typeof _libMixinsSingletonMixin2['default'], 'object');
25 | });
26 |
27 | it('getInstance, clearInstance', function () {
28 | var Foo = function Foo(x, y) {
29 | _classCallCheck(this, Foo);
30 |
31 | this.data = {
32 | x: x,
33 | y: y
34 | };
35 | };
36 |
37 | _lodash2['default'].assign(Foo, _libMixinsSingletonMixin2['default']);
38 |
39 | var foo = Foo.getInstance(1, 2);
40 | _powerAssert2['default'].deepEqual(foo.data, { x: 1, y: 2 });
41 | var foo2 = Foo.getInstance();
42 | (0, _powerAssert2['default'])(foo === foo2);
43 |
44 | Foo.clearInstance();
45 | var foo3 = Foo.getInstance(2, 3);
46 | (0, _powerAssert2['default'])(foo !== foo3);
47 | _powerAssert2['default'].deepEqual(foo3.data, { x: 2, y: 3 });
48 | });
49 | });
--------------------------------------------------------------------------------
/actions/GameActionCreators.es6:
--------------------------------------------------------------------------------
1 | import ACTIONS from 'consts/actions';
2 | import AppDispatcher from 'dispatcher/AppDispatcher';
3 |
4 |
5 | const GameActionCreators = {
6 |
7 | advanceToNextMaze() {
8 | AppDispatcher.getInstance().dispatch({
9 | type: ACTIONS.ADVANCE_TO_NEXT_MAZE
10 | });
11 | },
12 |
13 | assumePicksMode() {
14 | AppDispatcher.getInstance().dispatch({
15 | type: ACTIONS.ASSUME_PICKS_MODE
16 | });
17 | },
18 |
19 | cancelPicksMode() {
20 | AppDispatcher.getInstance().dispatch({
21 | type: ACTIONS.CANCEL_PICKS_MODE
22 | });
23 | },
24 |
25 | crushWallByPlayer(direction) {
26 | AppDispatcher.getInstance().dispatch({
27 | type: ACTIONS.CRUSH_WALL_BY_PLAYER,
28 | direction
29 | });
30 | },
31 |
32 | forwardGameTimeByFrame() {
33 | AppDispatcher.getInstance().dispatch({
34 | type: ACTIONS.FORWARD_GAME_TIME_BY_FRAME
35 | });
36 | },
37 |
38 | /* async */
39 | requestAddingGameResult(playerName) {
40 | AppDispatcher.getInstance().dispatch({
41 | type: ACTIONS.REQUEST_ADDING_GAME_RESULT,
42 | playerName
43 | });
44 | },
45 |
46 | resetGame() {
47 | AppDispatcher.getInstance().dispatch({
48 | type: ACTIONS.RESET_GAME
49 | });
50 | },
51 |
52 | saveDefeat() {
53 | AppDispatcher.getInstance().dispatch({
54 | type: ACTIONS.SAVE_DEFEAT
55 | });
56 | },
57 |
58 | saveVictory() {
59 | AppDispatcher.getInstance().dispatch({
60 | type: ACTIONS.SAVE_VICTORY
61 | });
62 | },
63 |
64 | walkPlayer(direction) {
65 | AppDispatcher.getInstance().dispatch({
66 | type: ACTIONS.WALK_PLAYER,
67 | direction
68 | });
69 | }
70 | };
71 |
72 |
73 | export default GameActionCreators;
74 |
--------------------------------------------------------------------------------
/dist/test/models/ThingIndexerModel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _uuid = require('uuid');
10 |
11 | var _uuid2 = _interopRequireDefault(_uuid);
12 |
13 | var _modelsThingIndexerModel = require('models/ThingIndexerModel');
14 |
15 | var _modelsThingIndexerModel2 = _interopRequireDefault(_modelsThingIndexerModel);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | it('should be defined', function () {
22 | _powerAssert2['default'].strictEqual(typeof _modelsThingIndexerModel2['default'], 'function');
23 | });
24 |
25 | it('update, get, getIds', function () {
26 | var indexer = new _modelsThingIndexerModel2['default']();
27 | _powerAssert2['default'].deepEqual(indexer.getIds(), []);
28 | var uuid = _uuid2['default'].v4();
29 | indexer.update(uuid, [1, 2]);
30 | indexer.update(uuid, [1, 3]);
31 | _powerAssert2['default'].deepEqual(indexer.get(uuid), [1, 3]);
32 | _powerAssert2['default'].deepEqual(indexer.getIds(), [uuid]);
33 | _powerAssert2['default'].strictEqual(indexer.get('not-existing-uuid'), null);
34 | });
35 |
36 | it('remove', function () {
37 | var indexer = new _modelsThingIndexerModel2['default']();
38 | var uuid1 = _uuid2['default'].v4();
39 | var uuid2 = _uuid2['default'].v4();
40 | indexer.update(uuid1, [1, 2]);
41 | indexer.update(uuid2, [1, 3]);
42 | _powerAssert2['default'].deepEqual(indexer.get(uuid1), [1, 2]);
43 | indexer.remove(uuid1);
44 | _powerAssert2['default'].strictEqual(indexer.get(uuid1), null);
45 | });
46 | });
--------------------------------------------------------------------------------
/dist/test/models/things/WallThingModel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _validator = require('validator');
10 |
11 | var _validator2 = _interopRequireDefault(_validator);
12 |
13 | var _modelsThingsWallThingModel = require('models/things/WallThingModel');
14 |
15 | var _modelsThingsWallThingModel2 = _interopRequireDefault(_modelsThingsWallThingModel);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | it('should be defined', function () {
22 | _powerAssert2['default'].strictEqual(typeof _modelsThingsWallThingModel2['default'], 'function');
23 | });
24 |
25 | it('uuid', function () {
26 | var thing = new _modelsThingsWallThingModel2['default']();
27 | (0, _powerAssert2['default'])(_validator2['default'].isUUID(thing.uuid, 4));
28 | });
29 |
30 | it('getTypeId', function () {
31 | var thing = new _modelsThingsWallThingModel2['default']();
32 | _powerAssert2['default'].strictEqual(thing.getTypeId(), 'wall');
33 | });
34 |
35 | it('getSymbol', function () {
36 | var thing = new _modelsThingsWallThingModel2['default']();
37 | _powerAssert2['default'].strictEqual(thing.getSymbol(), '#');
38 | });
39 |
40 | it('isPassable', function () {
41 | var thing = new _modelsThingsWallThingModel2['default']();
42 | _powerAssert2['default'].strictEqual(thing.isPassable(), false);
43 | });
44 |
45 | it('toContent', function () {
46 | var thing = new _modelsThingsWallThingModel2['default']();
47 | _powerAssert2['default'].strictEqual(thing.toContent(), '#');
48 | });
49 | });
--------------------------------------------------------------------------------
/lib/stages/index.es6:
--------------------------------------------------------------------------------
1 | import _s from 'underscore.string';
2 |
3 | import {createCounter, dictionarize} from 'lib/util';
4 |
5 | let counter = createCounter();
6 |
7 |
8 | export const Stage = {
9 | typeId: '_stage',
10 | sortOrder: 0,
11 | mazeCount: 1,
12 | timeLimit: 60000,
13 | bonusTimeThingCount: 5,
14 | penaltyTimeThingCount: 3,
15 | picksThingCount: 1,
16 | picksCount: 0,
17 | description: '----',
18 | getName() {
19 | return _s.titleize(_s.humanize(this.typeId));
20 | }
21 | };
22 |
23 |
24 | const SimpleStage = Object.assign({}, Stage, {
25 | typeId: 'simple',
26 | sortOrder: counter(),
27 | bonusTimeThingCount: 0,
28 | penaltyTimeThingCount: 0,
29 | picksThingCount: 0,
30 | description: 'Just run, no gimmick'
31 | });
32 |
33 | const EasyStage = Object.assign({}, Stage, {
34 | typeId: 'easy',
35 | sortOrder: counter(),
36 | picksCount: 1,
37 | timeLimit: 45000,
38 | description: 'Enable gimmicks'
39 | });
40 |
41 | const NormalStage = Object.assign({}, Stage, {
42 | typeId: 'normal',
43 | sortOrder: counter(),
44 | mazeCount: 2,
45 | timeLimit: 45000,
46 | picksCount: 1,
47 | description: 'Plural mazes continue'
48 | });
49 |
50 | const HardStage = Object.assign({}, Stage, {
51 | typeId: 'hard',
52 | sortOrder: counter(),
53 | mazeCount: 3,
54 | timeLimit: 45000,
55 | picksCount: 1,
56 | description: 'More difficult'
57 | });
58 |
59 | const LunaticStage = Object.assign({}, Stage, {
60 | typeId: 'lunatic',
61 | sortOrder: counter(),
62 | mazeCount: 5,
63 | timeLimit: 60000,
64 | picksCount: 2,
65 | description: 'For a person of leisure'
66 | });
67 |
68 |
69 | export const stageList = [
70 | SimpleStage,
71 | EasyStage,
72 | NormalStage,
73 | HardStage,
74 | LunaticStage
75 | ];
76 | export const stages = dictionarize(stageList, 'typeId');
77 |
--------------------------------------------------------------------------------
/dist/test/models/things/PlayerThingModel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4 |
5 | var _powerAssert = require('power-assert');
6 |
7 | var _powerAssert2 = _interopRequireDefault(_powerAssert);
8 |
9 | var _validator = require('validator');
10 |
11 | var _validator2 = _interopRequireDefault(_validator);
12 |
13 | var _modelsThingsPlayerThingModel = require('models/things/PlayerThingModel');
14 |
15 | var _modelsThingsPlayerThingModel2 = _interopRequireDefault(_modelsThingsPlayerThingModel);
16 |
17 | var _testSupportHelpers = require('test/support/helpers');
18 |
19 | describe((0, _testSupportHelpers.heading)(__filename), function () {
20 |
21 | it('should be defined', function () {
22 | _powerAssert2['default'].strictEqual(typeof _modelsThingsPlayerThingModel2['default'], 'function');
23 | });
24 |
25 | it('uuid', function () {
26 | var thing = new _modelsThingsPlayerThingModel2['default']();
27 | (0, _powerAssert2['default'])(_validator2['default'].isUUID(thing.uuid, 4));
28 | });
29 |
30 | it('getTypeId', function () {
31 | var thing = new _modelsThingsPlayerThingModel2['default']();
32 | _powerAssert2['default'].strictEqual(thing.getTypeId(), 'player');
33 | });
34 |
35 | it('getSymbol', function () {
36 | var thing = new _modelsThingsPlayerThingModel2['default']();
37 | _powerAssert2['default'].strictEqual(thing.getSymbol(), '@');
38 | });
39 |
40 | it('isPassable', function () {
41 | var thing = new _modelsThingsPlayerThingModel2['default']();
42 | _powerAssert2['default'].strictEqual(thing.isPassable(), true);
43 | });
44 |
45 | it('toContent', function () {
46 | var thing = new _modelsThingsPlayerThingModel2['default']();
47 | _powerAssert2['default'].strictEqual(thing.toContent(), '{magenta-fg}@{/}');
48 | });
49 | });
--------------------------------------------------------------------------------
/models/CellModel.es6:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | import Model from 'models/Model';
4 |
5 |
6 | export default class CellModel extends Model {
7 |
8 | constructor() {
9 | super();
10 |
11 | this._things = [];
12 | }
13 |
14 | getThings() {
15 | return this._things;
16 | }
17 |
18 | getThing() {
19 | return this.getThings()[0] || null;
20 | }
21 |
22 | getThingOrError() {
23 | let thing = this.getThing();
24 | if (thing) {
25 | return thing;
26 | } else {
27 | throw new Error('Can not get a thing');
28 | }
29 | }
30 |
31 | findThing(thing) {
32 | return _.find(this._things, function(thing_) {
33 | return thing === thing_;
34 | }) || null;
35 | }
36 |
37 | findThingOrError(thing) {
38 | let thing_ = this.findThing(thing);
39 | if (thing_) {
40 | return thing_;
41 | } else {
42 | throw new Error('Can not find the thing');
43 | }
44 | }
45 |
46 | hasThing(thing) {
47 | return !!this.findThing(thing);
48 | }
49 |
50 | setThing(thing) {
51 | if (this.hasThing(thing)) {
52 | throw new Error('The thing is duplicated');
53 | }
54 | this._things.push(thing);
55 | }
56 |
57 | /*
58 | * @param {Thing} thing
59 | * @return {boolean} Removed or not removed
60 | */
61 | removeThing(thing) {
62 | let removed = _.remove(this._things, function(thing_) {
63 | return thing === thing_;
64 | });
65 | return removed.length > 0;
66 | }
67 |
68 | isPassable() {
69 | if (this._things.length === 0) {
70 | return true;
71 | }
72 | return this._things.every(function(thing) {
73 | return thing.isPassable();
74 | });
75 | }
76 |
77 | toContent() {
78 | if (this._things.length > 0) {
79 | return this._things[0].toContent();
80 | } else {
81 | return ' ';
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/util.es6:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 |
3 | import conf from 'conf';
4 |
5 |
6 | export function createCounter(start = 1) {
7 | start -= 1;
8 | return () => start += 1;
9 | }
10 |
11 | export function calculateMillisecondsPerFrame() {
12 | return ~~(1000 / conf.fps);
13 | }
14 |
15 | /*
16 | * Convert from list