-
Notifications
You must be signed in to change notification settings - Fork 1
/
board.js
99 lines (84 loc) · 2.45 KB
/
board.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
size, map, flow, filter, constant, range, curry, find, join, getOr, forEach,
} from 'lodash/fp';
import { mapWithIndexes2d, log, printNewLine, createFilledArray } from './util';
import { applyRules } from './rule';
import { isAlive, ALIVE, DEAD } from './cellState';
const Column =
(cellStates) => ({
cellStates,
});
const Board =
(columns) => ({
columns,
});
export const CellPosition =
(column, row) => ({
column,
row,
});
const neighborVectors = [
[-1, -1], [0, -1], [+1, -1],
[-1, 0], [+1, 0],
[-1, +1], [0, +1], [+1, +1],
];
const mapNeighborCellPositions = curry(
(callback, cellPosition) =>
map(
flow(addVectorToCellPosition(cellPosition), callback),
neighborVectors));
const cellStatePath =
({ column, row }) =>
['columns', column, 'cellStates', row];
const getCellState = curry(
(board, cellPosition) =>
getOr(DEAD, cellStatePath(cellPosition), board));
const addVectorToCellPosition = curry(
(cellPosition, [x, y]) =>
CellPosition(cellPosition.column + x, cellPosition.row + y));
const countLiveNeighbors = curry(
(board, cellPosition) => flow(
mapNeighborCellPositions(getCellState(board)),
filter(isAlive),
size
)(cellPosition));
const boardToArray2d =
(board) =>
map('cellStates', board.columns);
const mapBoard = curry(
(callback, board) => flow(
boardToArray2d,
mapWithIndexes2d((cellState, x, y) => {
const cellPosition = CellPosition(x, y);
const liveNeighbors = countLiveNeighbors(board, cellPosition);
return callback({ cellState, cellPosition, liveNeighbors });
}),
map(Column),
Board
)(board));
const createEmptyBoard = curry(
({ columns, rows }) => flow(
range(0),
map(() => Column(createFilledArray(rows, DEAD))),
Board
)(columns));
export const initBoard = curry(
(seed, dimensions) => flow(
createEmptyBoard,
mapBoard(({ cellPosition }) =>
find(cellPosition, seed) ? ALIVE : DEAD)
)(dimensions));
export const generateBoard = curry(
(rules, board) =>
mapBoard(({ cellState, liveNeighbors }) =>
applyRules(rules, cellState, liveNeighbors),
board));
export const printBoard = curry(
(aliveChar, deadChar, board) => flow(
mapBoard(({ cellState }) =>
cellState === ALIVE ? aliveChar : deadChar),
boardToArray2d,
forEach(flow(join(' '), log)),
printNewLine,
constant(board) // Hacky way to force return values using flow
)(board));