-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* redux * wip * action * reducer * bitboard * genBitBoard * canmove * move * works * build
- Loading branch information
Showing
17 changed files
with
8,423 additions
and
5,557 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import * as _ from "lodash" | ||
import { octetCellsToCells, genOctetCells, OctetCells } from "GameDescription" | ||
|
||
interface BitBoardEntry { | ||
[key: number]: OctetCells | undefined | ||
} | ||
|
||
export const BitBoard: BitBoardEntry[] = _.range(1<<16).map(i => { | ||
const currCells = octetCellsToCells(i) | ||
let entry: BitBoardEntry = {} | ||
|
||
_.range(8).forEach(x => { | ||
if (currCells[x] !== ".") return | ||
const cells = _.clone(currCells) | ||
// 左方向 | ||
let lEnd = x | ||
if (x - 1 >= 0 && currCells[x - 1] === "w") { | ||
for (let j = x - 2; j >= 0; j--) { | ||
if (currCells[j] === "b") { | ||
lEnd = j | ||
break | ||
} | ||
if (currCells[j] === "." || currCells[j] === "-") break | ||
} | ||
} | ||
let rEnd = x | ||
if (x + 1 < 8 && currCells[x + 1] === "w") { | ||
for (let j = x + 2; j < 8; j++) { | ||
if (currCells[j] === "b") { | ||
rEnd = j | ||
break | ||
} | ||
if (currCells[j] === "." || currCells[j] === "-") break | ||
} | ||
} | ||
if (lEnd != rEnd) { | ||
for (let j = lEnd; j <= rEnd; j++) { | ||
cells[j] = "b" | ||
} | ||
entry[x] = genOctetCells(cells) | ||
} | ||
}) | ||
|
||
return entry | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import * as _ from "lodash" | ||
import { GameState } from "ui/containers/Game" | ||
import * as UiTypes from "ui/types" | ||
import { reverse } from "dns"; | ||
|
||
// 自石: 00 | ||
// 相手石: 01 | ||
// 空: 10 | ||
// 壁: 11 | ||
export type OctetCells = number | ||
|
||
export interface GameDescription { | ||
rows: OctetCells[] | ||
cols: OctetCells[] | ||
// 左下から右上 | ||
diagsR: OctetCells[] | ||
// 右下から左上 | ||
diagsL: OctetCells[] | ||
} | ||
|
||
export function fromUiState({ turn, cells }: GameState): GameDescription { | ||
const fpCells = turn == "b" ? cells : reverseColor(cells) | ||
|
||
const rows = _.chunk(fpCells, 8) | ||
.map(row => genOctetCells(row)) | ||
const cols = (_.zip.apply(null, _.chunk(fpCells, 8)) as Cell[][]) | ||
.map(col => genOctetCells(col)) | ||
const diagsR = genDiagsR(fpCells) | ||
.map(diag => genOctetCells(diag)) | ||
const diagsL = genDiagsL(fpCells) | ||
.map(diag => genOctetCells(diag)) | ||
|
||
return { rows, cols, diagsR, diagsL } | ||
} | ||
|
||
export function toUiState(desc: GameDescription, turn: UiTypes.Color): UiTypes.CellState[] { | ||
const cells = octetCellRowsToUiCells(desc.rows) | ||
return turn == "b" ? cells : reverseColor(cells) | ||
} | ||
|
||
type Cell = "." | "b" | "w" | "-" | ||
|
||
export function genOctetCells(row: Cell[]): OctetCells { | ||
return _.reduce( | ||
row, | ||
(octet, cell) => (octet << 2) + cellToByte(cell), | ||
0 | ||
) | ||
} | ||
|
||
function cellToByte(cell: Cell): number { | ||
if (cell === "b") return 0 | ||
if (cell === "w") return 1 | ||
if (cell === ".") return 2 | ||
return 3 | ||
} | ||
|
||
function genDiagsR(cells: Cell[]): Cell[][] { | ||
const rows = _.chunk(cells, 8) | ||
// (0, 0), (1, -1), (2, -2), ... | ||
// (0, 1), (1, 0), (2, -1), ... | ||
// (0, 2), (1, 1), (2, 0), ... | ||
// ... | ||
// (0, 7), (1, 6), ... | ||
const seg1 = _.range(8).map(idx => | ||
_.range(8).map(x => { | ||
const y = idx - x | ||
if (y < 0) return "-" | ||
return rows[y][x] | ||
}) | ||
) | ||
|
||
// (1, 7), (2, 6), ... | ||
// (2, 7), (3, 6), ... | ||
// (3, 7), (4, 6), ... | ||
// ... | ||
// (7, 7), *(8, 6), ... | ||
const seg2 = _.range(8).map(idxY => | ||
_.range(8).map(idxX => { | ||
const x = idxX + 1 + idxY | ||
const y = 7 - idxX | ||
if (x > 7) return "-" | ||
return rows[y][x] | ||
}) | ||
) | ||
|
||
return _.concat(seg1, seg2) | ||
} | ||
|
||
function genDiagsL(cells: Cell[]): Cell[][] { | ||
const rows = _.chunk(cells, 8) | ||
const seg1 = _.range(8).map(idx => | ||
_.range(8).map(x => { | ||
const y = idx - x | ||
if (y < 0) return "-" | ||
return rows[y][7 - x] | ||
}) | ||
) | ||
|
||
const seg2 = _.range(8).map(idxY => | ||
_.range(8).map(idxX => { | ||
const x = idxX + 1 + idxY | ||
const y = 7 - idxX | ||
if (x > 7) return "-" | ||
return rows[y][7 - x] | ||
}) | ||
) | ||
|
||
return _.concat(seg1, seg2) | ||
} | ||
|
||
function octetCellRowsToUiCells(rows: OctetCells[]): UiTypes.CellState[] { | ||
return _.flatten( | ||
rows.map(row => | ||
octetCellsToCells(row) as UiTypes.CellState[] | ||
) | ||
) | ||
} | ||
|
||
function reverseColor(cells: UiTypes.CellState[]): UiTypes.CellState[] { | ||
return cells.map(c => { | ||
if (c == "b") return "w" | ||
if (c == "w") return "b" | ||
return c | ||
}) | ||
} | ||
|
||
export function octetCellsToCells(octetCells: OctetCells): Cell[] { | ||
return _.range(8).map(idx => { | ||
const byte = (octetCells >> (2 * (7 - idx))) & 3 | ||
if (byte === 0) return "b" | ||
if (byte === 1) return "w" | ||
if (byte === 2) return "." | ||
return "-" | ||
}) | ||
} | ||
|
||
// for debug | ||
|
||
export function showOctetCols(cols: OctetCells[]) { | ||
const colCells = cols.map(octetCellsToCells) | ||
const str = _.range(8).map(y => | ||
_.range(8).map(x => | ||
colCells[x][y] | ||
).join("") | ||
).join("\n") | ||
console.log("--- debug show octet cols") | ||
console.log(str) | ||
} | ||
|
||
export function showOctetDiags(diags: OctetCells[]) { | ||
console.log("--- debug show octet diags") | ||
let rows: any = _.range(8).map(() => _.range(8)) | ||
diags.map((diag, idxY) => { | ||
const cells = octetCellsToCells(diag) | ||
if (idxY < 8) { | ||
_.range(8).forEach(x => { | ||
const y = idxY - x | ||
if (y < 0) return | ||
rows[y][x] = cells[x] | ||
}) | ||
} else { | ||
_.range(8).forEach(idxX => { | ||
const x = (idxY - 7) + idxX | ||
const y = 7 - idxX | ||
if (x > 7) return | ||
rows[y][x] = cells[idxX] | ||
}) | ||
} | ||
}) | ||
console.log(rows.map((row: any) => row.join("")).join("\n")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { GameDescription, fromUiState, toUiState, octetCellsToCells } from "GameDescription" | ||
import { BitBoard } from "BitBoard" | ||
import * as UiTypes from "ui/types" | ||
|
||
export function canMove(desc: GameDescription, x: number, y: number): boolean { | ||
// row | ||
if (BitBoard[desc.rows[y]][x]) return true | ||
// col | ||
if (BitBoard[desc.cols[x]][y]) return true | ||
// diagR | ||
const diagR = desc.diagsR[x + y] | ||
if (x + y < 8) { | ||
// seg1 | ||
if (BitBoard[diagR][x]) return true | ||
} else { | ||
// seg2 | ||
if (BitBoard[diagR][7 - y]) return true | ||
} | ||
// diagL | ||
const rx = 7 - x | ||
const diagL = desc.diagsL[rx + y] | ||
if (rx + y < 8) { | ||
// seg1 | ||
if (BitBoard[diagL][rx]) return true | ||
} else { | ||
// seg2 | ||
if (BitBoard[diagL][7 - y]) return true | ||
} | ||
return false | ||
} | ||
|
||
export function move(desc: GameDescription, x: number, y: number): GameDescription { | ||
const cells = toUiState(desc, "b") | ||
// row | ||
const nextRow = BitBoard[desc.rows[y]][x] | ||
if (nextRow) { | ||
octetCellsToCells(nextRow) | ||
.forEach((cell, ix) => { | ||
cells[8 * y + ix] = cell as UiTypes.CellState | ||
}) | ||
} | ||
// col | ||
const nextCol = BitBoard[desc.cols[x]][y] | ||
if (nextCol) { | ||
octetCellsToCells(nextCol) | ||
.forEach((cell, iy) => { | ||
cells[8 * iy + x] = cell as UiTypes.CellState | ||
}) | ||
} | ||
// diagR | ||
const diagR = desc.diagsR[x + y] | ||
if (x + y < 8) { | ||
// seg1 | ||
const nextDiag = BitBoard[diagR][x] | ||
if (nextDiag) { | ||
octetCellsToCells(nextDiag) | ||
.forEach((cell, ix) => { | ||
const iy = (x + y) - ix | ||
if (iy < 0) return | ||
cells[8 * iy + ix] = cell as UiTypes.CellState | ||
}) | ||
} | ||
} else { | ||
// seg2 | ||
const nextDiag = BitBoard[diagR][7 - y] | ||
if (nextDiag) { | ||
octetCellsToCells(nextDiag) | ||
.forEach((cell, i) => { | ||
const ix = (x + y - 7) + i | ||
const iy = 7 - i | ||
if (ix > 7) return | ||
cells[8 * iy + ix] = cell as UiTypes.CellState | ||
}) | ||
} | ||
} | ||
// diagL | ||
const rx = 7 - x | ||
const diagL = desc.diagsL[rx + y] | ||
if (rx + y < 8) { | ||
// seg1 | ||
const nextDiag = BitBoard[diagL][rx] | ||
if (nextDiag) { | ||
octetCellsToCells(nextDiag) | ||
.forEach((cell, ix) => { | ||
const iy = (rx + y) - ix | ||
if (iy < 0) return | ||
cells[8 * iy + 7 - ix] = cell as UiTypes.CellState | ||
}) | ||
} | ||
} else { | ||
// seg2 | ||
const nextDiag = BitBoard[diagL][7 - y] | ||
if (nextDiag) { | ||
octetCellsToCells(nextDiag) | ||
.forEach((cell, i) => { | ||
const ix = (rx + y - 7) + i | ||
const iy = 7 - i | ||
if (ix > 7) return | ||
cells[8 * iy + 7 - ix] = cell as UiTypes.CellState | ||
}) | ||
} | ||
} | ||
|
||
// TODO: たぶんdescに変換する処理を飛ばせる | ||
return fromUiState({ turn: "b", cells }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,38 @@ | ||
import * as React from "react" | ||
import * as ReactDOM from "react-dom" | ||
import { Board } from "ui/components/Board" | ||
import { InitialBoard } from "ui/constants" | ||
import { Store, Middleware } from "redux" | ||
import { applyMiddleware, createStore } from "redux" | ||
import { createLogger } from "redux-logger" | ||
import { Provider } from "react-redux" | ||
import { Game, GameState } from "ui/containers/Game" | ||
import { reducers } from "ui/reducers" | ||
import { initialBoard } from "ui/constants" | ||
|
||
export const App = () => ( | ||
<Board cells={InitialBoard} /> | ||
) | ||
const middleWares: Middleware[] = [ | ||
process.env.NODE_ENV !== "production" && createLogger() as any | ||
].filter(Boolean) | ||
|
||
export function start(dom: HTMLElement | null) { | ||
let store = createStore<GameState>( | ||
reducers, | ||
{ | ||
cells: initialBoard, | ||
turn: "b" | ||
}, | ||
applyMiddleware(...middleWares) | ||
) | ||
|
||
ReactDOM.render( | ||
<App />, | ||
<App store={store} />, | ||
dom | ||
) | ||
} | ||
|
||
export interface AppProps { | ||
store: Store<GameState> | ||
} | ||
const App = ({ store }: AppProps) => ( | ||
<Provider store={store}> | ||
<Game /> | ||
</Provider> | ||
) |
Oops, something went wrong.