diff --git a/actions/board/message.actions.js b/actions/board/message.actions.js index d8ee854..59048e5 100644 --- a/actions/board/message.actions.js +++ b/actions/board/message.actions.js @@ -1,13 +1,19 @@ export const MESSAGE_ACTION = 'MESSAGE_ACTION'; -export const DISPLAY = 'DISPLAY'; +export const SHOW = 'SHOW'; export const HIDE = 'HIDE'; +export const EXCLAIM = 'EXCLAIM'; -export const display = (message) => ({ +export const show = (message) => ({ type: MESSAGE_ACTION, - action: DISPLAY, + action: SHOW, message: message }); +export const exclaim = () => ({ + type: MESSAGE_ACTION, + action: EXCLAIM +}); + export const hide = () => ({ type: MESSAGE_ACTION, action: HIDE diff --git a/actions/board/troggle.actions.js b/actions/board/troggle.actions.js index bc0486e..473f533 100644 --- a/actions/board/troggle.actions.js +++ b/actions/board/troggle.actions.js @@ -1,16 +1,36 @@ export const TROGGLE_ACTION = 'TROGGLE_ACTION'; export const CREATE = 'CREATE'; export const MOVE = 'MOVE'; +export const FREEZE_ALL = 'FREEZE_ALL'; +export const UNFREEZE_ALL = 'UNFREEZE_ALL'; +export const CLEAR_ALL = 'CLEAR_ALL'; -export const create = () => ({ +export const create = (x, y) => ({ type: TROGGLE_ACTION, - action: CREATE + action: CREATE, + x: x, + y: y }); -export const move = (index, muncherX, muncherY) => ({ +export const move = (index, x, y) => ({ type: TROGGLE_ACTION, action: MOVE, index: index, - muncherX: muncherX, - muncherY: muncherY + x: x, + y: y +}); + +export const freezeAll = () => ({ + type: TROGGLE_ACTION, + action: FREEZE_ALL +}); + +export const unfreezeAll = () => ({ + type: TROGGLE_ACTION, + action: UNFREEZE_ALL +}); + +export const clearAll = () => ({ + type: TROGGLE_ACTION, + action: CLEAR_ALL }); diff --git a/components/board/board.component.js b/components/board/board.component.js index a077654..02c800c 100644 --- a/components/board/board.component.js +++ b/components/board/board.component.js @@ -11,6 +11,7 @@ import Muncher from './muncher.component'; import Troggle from './troggle.component'; import Values from '../../reducers/Values'; +import TroggleAI from '../../reducers/TroggleAI'; import { SETTINGS } from '../../App'; import * as BoardActions from '../../actions/board/board.actions'; @@ -19,44 +20,12 @@ import * as MessageActions from '../../actions/board/message.actions'; import * as MuncherActions from '../../actions/board/muncher.actions'; import * as TroggleActions from '../../actions/board/troggle.actions'; -const exclamations = [ - 'Congratulations!', - 'Yippee!', - 'Woohoo!', - 'Nice work!', - 'Great job!', - 'Boom!', - 'All finished!', - 'Shazam!' -]; - const troggleMoveTimers = []; const troggleCreateTimers = []; -// const toggleMoveTimeout = function() { -// this.props.dispatch(TroggleActions.move()); -// }; - -const continuations = { - muncher: null, - message: null -}; - let listener = null; export default class Board extends Component { - nextLevel() { - this.props.dispatch(BoardActions.nextLevel()); - - const troggleCount = 1; //Math.min(Math.ceil(this.props.board.level / 2), 5); - for (let i = 0; i < troggleCount; i++) { - this.props.dispatch(TroggleActions.create()); - troggleMoveTimers.push(setTimeout(this.moveTroggle.bind(this, i), 1000)); - } - - // toggleTimeout.call(this); - }; - componentDidMount() { listener = this.keydown.bind(this); window.addEventListener('keydown', listener); @@ -64,15 +33,57 @@ export default class Board extends Component { }; componentWillUnmount() { + this.clearTroggleTimers(); window.removeEventListener('keydown', listener); + }; - // destroy all troggle timers + nextLevel() { + this.props.dispatch(BoardActions.nextLevel()); + this.props.dispatch(TroggleActions.clearAll()); + this.clearTroggleTimers(); + this.createTroggles(); + }; + + clearTroggleTimers() { + troggleMoveTimers.forEach((timer) => { + clearTimeout(timer); + }); + + troggleCreateTimers.forEach((timer) => { + clearTimeout(timer); + }); + }; + + createTroggle(index) { + const newCoords = TroggleAI.create(); + this.props.dispatch(TroggleActions.create(newCoords.x, newCoords.y)); + troggleMoveTimers.push(setTimeout(this.moveTroggle.bind(this, index), 1000)); + }; + + createTroggles() { + const troggleCount = 3; //Math.min(Math.ceil(this.props.board.level / 2), 5); + for (let i = 0; i < troggleCount; i++) { + setTimeout(this.createTroggle.bind(this, i), (i + 1) * 5000); + } }; moveTroggle(index) { - this.props.dispatch(TroggleActions.move(index)); - clearTimeout(troggleMoveTimers[index]); - troggleMoveTimers[index] = setTimeout(this.moveTroggle.bind(this, index), 1000); + const newCoords = TroggleAI.move( + this.props.troggles[index].x, + this.props.troggles[index].y, + this.props.muncher.x, + this.props.muncher.y + ); + + if (newCoords.x === this.props.muncher.x && newCoords.y === this.props.muncher.y) { + this.props.dispatch(MessageActions.show('Eaten by a troggle!')); + this.props.dispatch(TroggleActions.clearAll()); + } + else { + this.props.dispatch(TroggleActions.move(index, newCoords.x, newCoords.y)); + clearTimeout(troggleMoveTimers[index]); + troggleMoveTimers[index] = setTimeout(this.moveTroggle.bind(this, index), 1000); + } }; // Keydown listener for spacebar, since it is bound to munch event and @@ -100,14 +111,13 @@ export default class Board extends Component { } else { const msg = Values.getError(board.values[index].value, board.level); - dispatch(MessageActions.display(msg)); + dispatch(MessageActions.show(msg)); dispatch(ScorebarActions.munchFailed()); dispatch(MuncherActions.freeze()); } if (Values.checkComplete(this.props.board.values, board.level)) { - const msg = exclamations[Math.floor(Math.random() * exclamations.length)]; - dispatch(MessageActions.display(msg)); + dispatch(MessageActions.exclaim()); } } }; diff --git a/reducers/TroggleAI.js b/reducers/TroggleAI.js new file mode 100644 index 0000000..688e9de --- /dev/null +++ b/reducers/TroggleAI.js @@ -0,0 +1,74 @@ +import { SETTINGS } from '../App'; + +const TroggleAI = { + move: function(currX, currY, muncherX, muncherY) { + // Randomize movement with boolean flags. + const moveToAttack = Boolean(Math.round(Math.random())); + const moveAlongXAxis = Boolean(Math.round(Math.random())); + const moveInPositiveDirection = Boolean(Math.round(Math.random())); + + let newX = currX; + let newY = currY; + + // DO NOT CONSOLIDATE. Attack first, ask questions later. + if (moveAlongXAxis === true) { + if (currX >= SETTINGS.GRID_WIDTH - 1 || + (moveToAttack && currX > muncherX)) { + newX = currX - 1; + } + else if (currX <= 0 || + (moveToAttack && currX < muncherX)) { + newX = currX + 1; + } + else if (moveInPositiveDirection) { + newX = currX + 1; + } + else if (!moveInPositiveDirection) { + newX = currX - 1; + } + } + else { + if (currY >= SETTINGS.GRID_HEIGHT - 1 || + (moveToAttack && currY > muncherY)) { + newY = currY - 1; + } + else if (currY <= 0 || + (moveToAttack && currY < muncherY)) { + newY = currY + 1; + } + else if (moveInPositiveDirection) { + newY = currY + 1; + } + else if (!moveInPositiveDirection) { + newY = currY - 1; + } + } + + return { x: newX, y: newY }; + }, + + create: function() { + // Start outside grid at a randomized location. + const enterOnXAxis = Boolean(Math.round(Math.random())); + const enterFromPositive = Boolean(Math.round(Math.random())); + + let x = -1; + let y = -1; + + if (enterFromPositive === true) { + x = SETTINGS.GRID_WIDTH; + y = SETTINGS.GRID_HEIGHT; + } + + if (enterOnXAxis === true) { + y = Math.round(Math.random() * (SETTINGS.GRID_HEIGHT - 1)); + } + else { + x = Math.round(Math.random() * (SETTINGS.GRID_WIDTH - 1)); + } + + return { x: x, y: y } + } +}; + +export default TroggleAI; diff --git a/reducers/board/message.reducer.js b/reducers/board/message.reducer.js index 60bcf7b..1a5cc14 100644 --- a/reducers/board/message.reducer.js +++ b/reducers/board/message.reducer.js @@ -1,5 +1,16 @@ const Immutable = require('immutable'); +const exclamations = [ + 'Congratulations!', + 'Yippee!', + 'Woohoo!', + 'Nice work!', + 'Great job!', + 'Boom!', + 'All finished!', + 'Shazam!' +]; + import * as MessageActions from '../../actions/board/message.actions'; const initial = { message: '', hidden: true }; @@ -10,7 +21,14 @@ const reducer = (state = initial, action) => { } switch (action.action) { - case MessageActions.DISPLAY: + case MessageActions.EXCLAIM: + const msg = exclamations[Math.floor(Math.random() * exclamations.length)]; + return Immutable.Map(state) + .set('hidden', false) + .set('message', msg) + .toObject(); + + case MessageActions.SHOW: return Immutable.Map(state) .set('hidden', false) .set('message', action.message) diff --git a/reducers/board/troggle.reducer.js b/reducers/board/troggle.reducer.js index b6ee755..47cfb97 100644 --- a/reducers/board/troggle.reducer.js +++ b/reducers/board/troggle.reducer.js @@ -1,7 +1,6 @@ const Immutable = require('immutable'); import * as TroggleActions from '../../actions/board/troggle.actions'; -import { SETTINGS } from '../../App'; const initial = []; const reducer = (state = initial, action) => { @@ -11,59 +10,21 @@ const reducer = (state = initial, action) => { switch (action.action) { case TroggleActions.MOVE: - // Randomize movement with boolean flags. - const moveToAttack = Boolean(Math.round(Math.random())); - const moveAlongXAxis = Boolean(Math.round(Math.random())); - const moveInPositiveDirection = Boolean(Math.round(Math.random())); - - const x = state[action.index].x; - const y = state[action.index].y; - let newX = x; - let newY = y; - - // DO NOT CONSOLIDATE. Attack first, ask questions later. - if (moveAlongXAxis === true) { - if (x === SETTINGS.GRID_WIDTH - 1 || - (moveToAttack && x >= action.muncherX)) { - newX = x - 1; - } - else if (x === 0 || - (moveToAttack && x < action.muncherX)) { - newX = x + 1; - } - else if (moveInPositiveDirection) { - newX = x + 1; - } - else if (!moveInPositiveDirection) { - newX = x - 1; - } - } - else { - if (y === SETTINGS.GRID_HEIGHT - 1 || - (moveToAttack && y >= action.muncherY)) { - newY = y - 1; - } - else if (y === 0 || - (moveToAttack && y < action.muncherY)) { - newY = y + 1; - } - else if (moveInPositiveDirection) { - newY = y + 1; - } - else if (!moveInPositiveDirection) { - newY = y - 1; - } - } - return Immutable.fromJS(state) - .setIn([action.index, 'x'], newX) - .setIn([action.index, 'y'], newY) + .setIn([action.index, 'x'], action.x) + .setIn([action.index, 'y'], action.y) .toJS(); case TroggleActions.CREATE: - return Immutable.List(state).push({ x: 0, y: 0 }).toArray(); - break; - } + return Immutable.List(state).push({ x: action.x, y: action.y }).toArray(); + + case TroggleActions.FREEZE_ALL: + + case TroggleActions.UNFREEZE_ALL: + + case TroggleActions.CLEAR_ALL: + return Immutable.List().toArray(); + }; return state; }; diff --git a/sass/board/board.scss b/sass/board/board.scss index f63fde5..8426e2c 100644 --- a/sass/board/board.scss +++ b/sass/board/board.scss @@ -3,7 +3,7 @@ position:relative; width:600px; - @for $i from 0 through 6 { + @for $i from -1 through 7 { .x#{$i} { left: #{$i * 100}px; }