@@ -2,112 +2,172 @@ import * as actionTypes from "../constants/actionTypes";
import * as _ from 'lodash';
import {selected} from "./selected";
import {paths} from "./paths";
import {threats} from "./threats";


const initPiecesPlacement = {
'A8': {type: 'Rook', color: 'B', selected: false},
'B8': {type: 'Knight', color: 'B', selected: false},
'C8': {type: 'Bishop', color: 'B', selected: false},
'D8': {type: 'Queen', color: 'B', selected: false},
'E8': {type: 'King', color: 'B', selected: false},
'F8': {type: 'Bishop', color: 'B', selected: false},
'G8': {type: 'Knight', color: 'B', selected: false},
'H8': {type: 'Rook', color: 'B', selected: false},
'A7': {type: 'Pawn', color: 'B', selected: false},
'B7': {type: 'Pawn', color: 'B', selected: false},
'C7': {type: 'Pawn', color: 'B', selected: false},
'D7': {type: 'Pawn', color: 'B', selected: false},
'E7': {type: 'Pawn', color: 'B', selected: false},
'F7': {type: 'Pawn', color: 'B', selected: false},
'G7': {type: 'Pawn', color: 'B', selected: false},
'H7': {type: 'Pawn', color: 'B', selected: false},
'A6': {type: null, color: null, selected:false},
'B6': {type: null, color: null, selected:false},
'C6': {type: null, color: null, selected:false},
'D6': {type: null, color: null, selected:false},
'E6': {type: null, color: null, selected:false},
'F6': {type: null, color: null, selected:false},
'G6': {type: null, color: null, selected:false},
'H6': {type: null, color: null, selected:false},
'A5': {type: null, color: null, selected:false},
'B5': {type: null, color: null, selected:false},
'C5': {type: null, color: null, selected:false},
'D5': {type: null, color: null, selected:false},
'E5': {type: null, color: null, selected:false},
'F5': {type: null, color: null, selected:false},
'G5': {type: null, color: null, selected:false},
'H5': {type: null, color: null, selected:false},
'A4': {type: null, color: null, selected:false},
'B4': {type: null, color: null, selected:false},
'C4': {type: null, color: null, selected:false},
'D4': {type: null, color: null, selected:false},
'E4': {type: null, color: null, selected:false},
'F4': {type: null, color: null, selected:false},
'G4': {type: null, color: null, selected:false},
'H4': {type: null, color: null, selected:false},
'A3': {type: null, color: null, selected:false},
'B3': {type: null, color: null, selected:false},
'C3': {type: null, color: null, selected:false},
'D3': {type: null, color: null, selected:false},
'E3': {type: null, color: null, selected:false},
'F3': {type: null, color: null, selected:false},
'G3': {type: null, color: null, selected:false},
'H3': {type: null, color: null, selected:false},
'A2': {type: 'Pawn', color: 'W', selected: false},
'B2': {type: 'Pawn', color: 'W', selected: false},
'C2': {type: 'Pawn', color: 'W', selected: false},
'D2': {type: 'Pawn', color: 'W', selected: false},
'E2': {type: 'Pawn', color: 'W', selected: false},
'F2': {type: 'Pawn', color: 'W', selected: false},
'G2': {type: 'Pawn', color: 'W', selected: false},
'H2': {type: 'Pawn', color: 'W', selected: false},
'A1': {type: 'Rook', color: 'W', selected: false},
'B1': {type: 'Knight', color: 'W', selected: false},
'C1': {type: 'Bishop', color: 'W', selected: false},
'D1': {type: 'Queen', color: 'W', selected: false},
'E1': {type: 'King', color: 'W', selected: false},
'F1': {type: 'Bishop', color: 'W', selected: false},
'G1': {type: 'Knight', color: 'W', selected: false},
'H1': {type: 'Rook', color: 'W', selected: false},
'A8': {type: 'Rook', color: 'B', selected: false},
'B8': {type: 'Knight', color: 'B', selected: false},
'C8': {type: 'Bishop', color: 'B', selected: false},
'D8': {type: 'Queen', color: 'B', selected: false},
'E8': {type: 'King', color: 'B', selected: false},
'F8': {type: 'Bishop', color: 'B', selected: false},
'G8': {type: 'Knight', color: 'B', selected: false},
'H8': {type: 'Rook', color: 'B', selected: false},
'A7': {type: 'Pawn', color: 'B', selected: false},
'B7': {type: 'Pawn', color: 'B', selected: false},
'C7': {type: 'Pawn', color: 'B', selected: false},
'D7': {type: 'Pawn', color: 'B', selected: false},
'E7': {type: 'Pawn', color: 'B', selected: false},
'F7': {type: 'Pawn', color: 'B', selected: false},
'G7': {type: 'Pawn', color: 'B', selected: false},
'H7': {type: 'Pawn', color: 'B', selected: false},
'A6': {type: null, color: null, selected:false},
'B6': {type: null, color: null, selected:false},
'C6': {type: null, color: null, selected:false},
'D6': {type: null, color: null, selected:false},
'E6': {type: null, color: null, selected:false},
'F6': {type: null, color: null, selected:false},
'G6': {type: null, color: null, selected:false},
'H6': {type: null, color: null, selected:false},
'A5': {type: null, color: null, selected:false},
'B5': {type: null, color: null, selected:false},
'C5': {type: null, color: null, selected:false},
'D5': {type: null, color: null, selected:false},
'E5': {type: null, color: null, selected:false},
'F5': {type: null, color: null, selected:false},
'G5': {type: null, color: null, selected:false},
'H5': {type: null, color: null, selected:false},
'A4': {type: null, color: null, selected:false},
'B4': {type: null, color: null, selected:false},
'C4': {type: null, color: null, selected:false},
'D4': {type: null, color: null, selected:false},
'E4': {type: null, color: null, selected:false},
'F4': {type: null, color: null, selected:false},
'G4': {type: null, color: null, selected:false},
'H4': {type: null, color: null, selected:false},
'A3': {type: null, color: null, selected:false},
'B3': {type: null, color: null, selected:false},
'C3': {type: null, color: null, selected:false},
'D3': {type: null, color: null, selected:false},
'E3': {type: null, color: null, selected:false},
'F3': {type: null, color: null, selected:false},
'G3': {type: null, color: null, selected:false},
'H3': {type: null, color: null, selected:false},
'A2': {type: 'Pawn', color: 'W', selected: false},
'B2': {type: 'Pawn', color: 'W', selected: false},
'C2': {type: 'Pawn', color: 'W', selected: false},
'D2': {type: 'Pawn', color: 'W', selected: false},
'E2': {type: 'Pawn', color: 'W', selected: false},
'F2': {type: 'Pawn', color: 'W', selected: false},
'G2': {type: 'Pawn', color: 'W', selected: false},
'H2': {type: 'Pawn', color: 'W', selected: false},
'A1': {type: 'Rook', color: 'W', selected: false},
'B1': {type: 'Knight', color: 'W', selected: false},
'C1': {type: 'Bishop', color: 'W', selected: false},
'D1': {type: 'Queen', color: 'W', selected: false},
'E1': {type: 'King', color: 'W', selected: false},
'F1': {type: 'Bishop', color: 'W', selected: false},
'G1': {type: 'Knight', color: 'W', selected: false},
'H1': {type: 'Rook', color: 'W', selected: false},
};
const initPath = {move:[], eat:[]};

export const board = (state = {pieces: initPiecesPlacement, paths: initPath}, action) => {
switch (action.type) {
case actionTypes.SELECTED_PIECE:
return {
...state, pieces: _.mapValues(state.pieces, (value, key) => {
let sel = selected({[key]: value}, action);
return sel[_.keys(sel)[0]]})};
export const board = (state = {checked: null, checkmate:false, pieces: initPiecesPlacement, paths: initPath}, action) => {
switch (action.type) {
case actionTypes.SELECTED_PIECE:
return {
...state, pieces: _.mapValues(state.pieces, (value, key) => {
let sel = selected({[key]: value}, action);
//this sucks
return sel[_.keys(sel)[0]]
})
};

case actionTypes.CALCULATE_PATH:
return {...state, paths: paths(state.paths, action)};

case actionTypes.CALCULATE_PATH:
return {...state, paths: paths(state.paths, action)};
case actionTypes.GET_CHECKED:
let selectedPlacement = findSelected(state.pieces);
let newPathsMove = getPathsThatDontCheck(selectedPlacement,state.paths.move,state.pieces,action);
let newPathsEat = getPathsThatDontCheck(selectedPlacement,state.paths.eat,state.pieces,action);
return {...state, paths: {move:newPathsMove, eat:newPathsEat}};


case actionTypes.PIECE_MOVED:
//check if placement in paths move
if(state.paths.move.includes(action.newPlacement)) {
return {
...state, pieces: Object.assign({}, state.pieces, {
[action.newPlacement]: selected({[action.newPlacement]: state.pieces[action.oldPlacement]}, action),
[action.oldPlacement]: {type: null, color: null, selected: false}}),paths: paths(state.paths, action)
};
}
return state;
case actionTypes.IS_CHECKMATE:
let checkedColorPieces =[];
_.forEach(state.pieces, (piece, key) =>{
if(piece.color === action.color) {
checkedColorPieces.push({[key]: piece});
}
});
_.forEach(checkedColorPieces, (piece, placement)=>{
let newPathsMove = getPathsThatDontCheck(placement,state.paths.move,state.pieces,action);
let newPathsEat = getPathsThatDontCheck(placement,state.paths.eat,state.pieces,action);

case actionTypes.PIECE_TRY_EAT:
//check if placement in paths eat
if(state.paths.eat.includes(action.newPlacement)) {
return {
...state, pieces: Object.assign({}, state.pieces, {
[action.newPlacement]: selected({[action.newPlacement]: state.pieces[action.oldPlacement]}, action),
[action.oldPlacement]: {type: null, color: null, selected: false}
}), paths: paths(state.paths, action)
};
}
return state;
default:
return state
}
if(!_.isEmpty(newPathsMove) || !_.isEmpty(newPathsEat))
{
return state
}
});
return {...state, checkmate:true};


case actionTypes.RESET_CHECK:
return {...state, checked:null};
case actionTypes.CHECK:
let threat = threats([], action);
let placementsThatCheck = paths(threat, action);
if(!_.isEmpty(placementsThatCheck)){
return {...state, checked:action.color};
}
return state;

case actionTypes.PIECE_MOVED:
//check if placement in paths move
if(state.paths.move.includes(action.newPlacement)) {
return {
...state, pieces: Object.assign({}, state.pieces, {
[action.newPlacement]: selected({[action.newPlacement]: state.pieces[action.oldPlacement]}, action),
[action.oldPlacement]: {type: null, color: null, selected: false}}),paths: paths(state.paths, action)
};
}
console.log('illegal move');
return state;

case actionTypes.PIECE_TRY_EAT:
//check if placement in paths eat
if(state.paths.eat.includes(action.newPlacement)) {
return {
...state, pieces: Object.assign({}, state.pieces, {
[action.newPlacement]: selected({[action.newPlacement]: state.pieces[action.oldPlacement]}, action),
[action.oldPlacement]: {type: null, color: null, selected: false}
}), paths: paths(state.paths, action)
};
}
console.log('illegal eat move');
return state;

default:
return state
}
};

const findSelected = (pieces) =>{
return _.findKey(pieces, (piece) => { return piece.selected})
};
const move = (pieces, firstPlacement, secondPlacement) => {
return {...pieces, [secondPlacement]:pieces[firstPlacement], [firstPlacement]: {type: null, color: null, selected: false}};
};

const getPathsThatDontCheck = (selectedPlacement, path, pieces, action) =>{
return _.filter(path, (placement) =>{
let currentPieces = move(pieces, selectedPlacement, placement);
let newAction = {...action, pieces:currentPieces};
let threat = threats([], newAction);
let placementsThatCheck = paths(threat, newAction);
if(_.isEmpty(placementsThatCheck)){
return true;
}
});
};
@@ -7,53 +7,5 @@ const rootReducer = combineReducers({
turn,
});

// const rootReducer = (state = {}, action) => {
// switch (action.type) {
// case 'CELL_CLICKED':
// console.log(state.turn + ' turn');
// console.log(state.turn + ' ' + action.pieceType.type + ' Clicked at ' + action.placement);
// return state;
// case actionTypes.CHANGED_SELECTED_PIECE:
// let paths = calculatePath(state.pieces, action.pieceType, action.placement);
// console.log(paths);
// return {...state, paths: paths};
//
// //move
// if (state.selected !== '' && state.selected.pieceType.type !== undefined) {
// if (state.paths[0].includes(action.placement) || state.paths[1].includes(action.placement)) {
// let formerPlacement = state.selected.placement;
// let newPlacement = action.placement;
// let newPlacementPiece = state.pieces[state.selected.placement];
// return {
// ...state, pieces: Object.assign({}, state.pieces, {
// [formerPlacement]: {},
// [newPlacement]: {type: newPlacementPiece.type, color: newPlacementPiece.color}
// }),
// selected: '', paths: [[], []], turn: state.turn === 'W' ? 'B' : 'W'
// };
// }
// else {
// //error: an illegal move
// console.log('illegal move');
// return {...state, selected: '', paths: [[], []]}
// }
// }
// else {
// if (state.selected === '' && action.pieceType.type !== undefined && action.pieceType.color === state.turn) {
// console.log('selected a piece');
// let paths = calculatePath(state.pieces, action.pieceType, action.placement);
// console.log(paths);
// return {...state, selected: {placement: action.placement, pieceType: action.pieceType}, paths: paths};
// }
// else {
// console.log('not ' + action.pieceType.color + 'turn');
// return {...state, selected: {placement: action.placement, pieceType: action.pieceType}};
// }
// }
// default:
// return state;
// }
// };


export default rootReducer;

Large diffs are not rendered by default.

@@ -9,14 +9,12 @@ export const selected = (state, action) => {
else{
//only way i know how to accsess the keys dynamically right now is withs keys and then the first place.
let piece = {...state[keys(state)[0]], selected:false};
let nextState = {[keys(state)[0]]: piece};
return nextState;
return {[keys(state)[0]]: piece};
}
case actionTypes.PIECE_TRY_EAT:
case actionTypes.PIECE_MOVED:
//modifies state to just a piece with no placement
let nextState = {...state[keys(state)[0]], selected:false};
return nextState;
return {...state[keys(state)[0]], selected: false};

default:
return state
@@ -0,0 +1,102 @@
import * as actionTypes from "../constants/actionTypes";
import * as _ from 'lodash';
import {BLACK, WHITE} from "../constants/index";
import {separatePlacement} from "./paths";


export const threats = (state = [], action) => {
switch(action.type){
case actionTypes.CHECK:
return getThreats(action.pieces, action.color);
case actionTypes.GET_CHECKED:
return getThreats(action.pieces, action.color)
default:
return state
}
};

const getThreats = (pieces, colorToCheck) => {
let kingPlacement = findKingPlacement(pieces,colorToCheck);
let enemyColor = colorToCheck === WHITE ? BLACK : WHITE;
let threatPlacements =[];
_.forEach(pieces, (piece, key)=>{
if(piece.color === enemyColor){
if(checkPiece(key, piece, kingPlacement)){
threatPlacements.push(key);
}
}
});
return threatPlacements
};

export const findKingPlacement = (pieces, kingColor) => {
let kingsPlacement = '';
_.forEach(pieces, (piece, key) => {
if(piece.color === kingColor && piece.type === 'King'){
kingsPlacement = key
}
});
return kingsPlacement
};

const checkPiece = (placement, piece, enemyKingPlacement) => {
let isThreatening = false;
switch (piece.type) {
case 'Pawn':
isThreatening = pawnThreat(placement, enemyKingPlacement);
break;
case 'Bishop':
isThreatening = bishopThreat(placement, enemyKingPlacement);
break;
case 'Rook':
isThreatening = rookThreat(placement, enemyKingPlacement);
break;
case 'Queen':
isThreatening = queenThreat(placement, enemyKingPlacement);
break;
case 'Knight':
isThreatening = knightThreat(placement, enemyKingPlacement);
break;
case 'King':
//a king can never threaten other team's king
break;
default:
break;
}
return isThreatening
};

const pawnThreat = (placement, enemyKingPlacement) =>{
let placementsAbsDiff = placementsAbsoluteDiff(placement, enemyKingPlacement);
return (placementsAbsDiff.letterDiff === 1 && placementsAbsDiff.numberDiff === 1)
};
const bishopThreat = (placement, enemyKingPlacement) =>{
let placementAbsDiff = placementsAbsoluteDiff(placement, enemyKingPlacement);
return (placementAbsDiff.letterDiff === placementAbsDiff.numberDiff);
};
const rookThreat = (placement, enemyKingPlacement) =>{
let placementAbsDiff = placementsAbsoluteDiff(placement, enemyKingPlacement);
return (placementAbsDiff.letterDiff === 0 || placementAbsDiff.numberDiff === 0);
};
const queenThreat = (placement, enemyKingPlacement) =>{
return (bishopThreat(placement, enemyKingPlacement) || rookThreat(placement, enemyKingPlacement))
};
const knightThreat = (placement, enemyKingPlacement) =>{
let placementAbsDiff = placementsAbsoluteDiff(placement, enemyKingPlacement);
return ((placementAbsDiff.letterDiff === 2 && placementAbsDiff.numberDiff === 1)
|| (placementAbsDiff.letterDiff === 1 && placementAbsDiff.numberDiff === 2))
};
const placementsAbsoluteDiff = (threatenPlacement, kingPlacement) => {
let threatenPlacementSep = separatePlacement(threatenPlacement);
let kingPlacementSep = separatePlacement(kingPlacement);
return {letterDiff:Math.abs(placementsLetterDiff(threatenPlacementSep.letter, kingPlacementSep.letter)),
numberDiff: Math.abs(placementsNumberDiff(threatenPlacementSep.number, kingPlacementSep.number))}

};
const placementsLetterDiff = (firstLetter, secondLetter) =>{
return firstLetter.charCodeAt(0) - secondLetter.charCodeAt(0);
};
const placementsNumberDiff = (firstNum, secondNum) =>{
//they come as strings
return parseInt(firstNum) - parseInt(secondNum)
};

Large diffs are not rendered by default.

@@ -1,13 +1,15 @@
import {SWITCH_TURN} from "../constants/actionTypes";
import {TURN_ENDED} from "../constants/actionTypes";
import {BLACK, WHITE} from "../constants/index";

export const turn = (state = WHITE, action) => {
switch (action.type) {
case SWITCH_TURN:
if(action.isSelected){
return state === WHITE ? state : BLACK;
case TURN_ENDED:
if(action.selected){
return state === WHITE ? BLACK : WHITE;
}
else{
return state
}
else return state;
default:
return state
}