tsgammon-core
Version:
A Backgammon library for Typescript, formerly developed as a part of tsgammon-ui
77 lines (72 loc) • 2.72 kB
text/typescript
import { BoardStateNode, NoMove, NO_MOVE, wrap } from '../BoardStateNode'
import { findMove } from './findMove'
/**
* 与えられたBoardStateNodeについて、指定された位置へ駒を動かすムーブがあれば、それを返す
* @param node
* @param pos
* @param useMinorFirst
* @returns
*/
export function makeLeap(
node: BoardStateNode,
pos: number,
useMinorFirst: boolean
): BoardStateNode | NoMove {
const dices = node.dices.filter((d) => !d.used)
if (dices.length == 0) {
return NO_MOVE
}
// まず、一つだけですむケースを探す
const { major, minor } =
dices.length >= 2
? dices[0].pip > dices[1].pip
? { major: dices[0].pip, minor: dices[1].pip }
: { major: dices[1].pip, minor: dices[0].pip }
: { major: dices[0].pip, minor: undefined }
const withMajor =
pos - major >= 0 ? findMove(node, pos - major, false) : NO_MOVE
// 本来はここでもuseMinorFirstを意識しないといけないが、この関数はmakePointの後で
// 使用する想定なので、major/minorの両方で駒が動かせる時は、そちらで拾われることになり
// 意識する意味がない
if (
withMajor.hasValue &&
withMajor.lastMoves()[withMajor.lastMoves().length - 1].to === pos
) {
return withMajor
}
if (minor === undefined) {
return NO_MOVE
}
const withMinor =
pos - minor >= 0 ? findMove(node, pos - minor, true) : NO_MOVE
if (
withMinor.hasValue &&
withMinor.lastMoves()[withMinor.lastMoves().length - 1].to === pos
) {
return withMinor
}
// 二つ使う場合は、useMinorFirstを反映させる
const from = pos - (major + minor)
const leap = wrap(node)
.apply((node) => findMove(node, from, useMinorFirst))
.apply((node) => makeLeap(node, pos, useMinorFirst)).unwrap
if (leap.hasValue) {
return leap
}
// ゾロ目でないなら、これ以上のサーチは不要
if (dices.length < 3) {
return NO_MOVE
}
// 残りのダイス(全て同じ目とする)が使えるかどうかは再帰して判定する
return (
wrap(node)
// 一つ前のポイントをクリックした状態を生成
.apply((node) =>
pos - major >= 0
? makeLeap(node, pos - major, useMinorFirst)
: NO_MOVE
)
// 一つ前のポイントにきた駒をクリックして進めた状態を生成
.apply((node) => findMove(node, pos - major, useMinorFirst)).unwrap
)
}