import { Define } from './define'; export class Koma { public readonly value: Define.KomaValue; private constructor(value: Define.KomaValue) { this.value = value; } //they are all static value, so these object are going to match to the same koma public static empty = new Koma(Define.empty); public static hidden = new Koma(Define.hidden); public static shi = new Koma(Define.shi); public static gon = new Koma(Define.gon); public static bakko = new Koma(Define.bakko); public static gin = new Koma(Define.gin); public static kin = new Koma(Define.kin); public static kaku = new Koma(Define.kaku); public static hisha = new Koma(Define.hisha); public static ou = new Koma(Define.ou); public static gyoku = new Koma(Define.gyoku); public static fromStr(val: string) { if (val === Define.empty) { return Koma.empty; } if (val === Define.hidden) { return Koma.hidden; } if (val === Define.shi) { return Koma.shi; } if (val === Define.gon) { return Koma.gon; } if (val === Define.bakko) { return Koma.bakko; } if (val === Define.gin) { return Koma.gin; } if (val === Define.kin) { return Koma.kin; } if (val === Define.kaku) { return Koma.kaku; } if (val === Define.hisha) { return Koma.hisha; } if (val === Define.ou) { return Koma.ou; } if (val === Define.gyoku) { return Koma.gyoku; } throw new Error("Invalid koma value " + val + " was given"); } public get score(): number { if (this === Koma.hidden) { throw new Error("cannot get the score of Koma.hidden"); } let n = Number(this.value); return Math.floor(n / 2) * 10 + 10; } public get Text(): string { let text = ''; switch (this.value) { case Define.empty: text = ""; break; // candidates ☖☐☗◼◯ case Define.hidden: text = "[]"; break; case Define.shi: text = "し"; break; case Define.gon: text = "香"; break; case Define.bakko: text = "馬"; break; case Define.gin: text = "銀"; break; case Define.kin: text = "金"; break; case Define.kaku: text = "角"; break; case Define.hisha: text = "飛"; break; case Define.ou: text = "王"; break; case Define.gyoku: text = "玉"; break; default: break; } return text; } public get isKing(): boolean { return this.value === Define.ou || this.value === Define.gyoku; } public get isShi(): boolean { return this.value === Define.shi; } public get isHidden(): boolean { return this.value === Define.hidden; } public get isEmpty(): boolean { return this.value === Define.empty; } /** return if this koma equals to the given koma. exception: "The OU equals the GYOKU" */ public equals(target: Koma): boolean { if (target === undefined || target === null) { return false; } if (this.isKing && target.isKing) { return true; } return this.value === target.value; } /** return if this koma equals to the given koma. */ public equalsExact(target: Koma): boolean { if (target === undefined || target === null) { return false; } return this.value === target.value; } public canBlock(attack: Koma): boolean { if (this.equals(attack)) { return true; } if (this.isKing) { if (attack.value === Define.shi || attack.value === Define.gon) { return false; } return true; } return false; } public toString(): string { return this.value; } } export class KomaArray { //currently cannot extends Array.prototype ES5. //implement array methods as util class instead to extend prototype. public static findIndex(target: Array, koma: Koma): number { for (let i = 0; i < (target.length | 0); i = (i + 1) | 0) { if (target[i].equals(koma)) { return i; } } return -1; } public static findIndexExact(target: Array, koma: Koma): number { for (let i = 0; i < (target.length | 0); i = (i + 1) | 0) { if (target[i].equalsExact(koma)) { return i; } } return -1; } public static contains(target: Array, koma: Koma): boolean { return target.some((k) => k.equals(koma)); } public static containsExact(target: Array, koma: Koma): boolean { return target.some((k) => k.equalsExact(koma)); } public static count(target: Array, koma: Koma): number { return target.filter((k) => koma.equals(k)).length; } public static countExact(target: Array, koma: Koma): number { return target.filter((k) => koma.equalsExact(k)).length; } public static sortAsc(target: Array): void { target.sort(KomaArray.comparerAsc); }; public static sortDesc(target: Array): void { target.sort(KomaArray.comparerDesc); }; private static comparerDesc(a: Koma, b: Koma): number { if (a.value > b.value) { return -1; } if (a.value < b.value) { return 1; } return 0; } private static comparerAsc(a: Koma, b: Koma): number { return -KomaArray.comparerDesc(a, b); } public static getUnique(target: Koma[]): Array { let uniqueList = new Array(); const targetLen = target.length; for (let i = 0; i < targetLen; i = (i + 1) | 0) { let koma = target[i]; if (koma.equals(Koma.empty)) { continue; } if (KomaArray.containsExact(uniqueList, koma)) { continue; } uniqueList.push(koma); } return uniqueList; } public static createFrom(hand_or_field: string) { let a = new Array(); for (let i = 0; i < (hand_or_field.length | 0); i = (i + 1) | 0) { a[i] = Koma.fromStr(hand_or_field[i]); } return a; } public static createEmptyField(): Array { let str = ""; for (let i = 0; i < (Define.maxFieldLength | 0); i = (i + 1) | 0) { str += Koma.empty.value; } return KomaArray.createFrom(str); } public static toString(target: Array): string { return target.join(''); } public static toTextString(target: Array): string { return target.map(k => k.Text).join(''); } public static getLength(target: Array): number { return target.filter((k) => k !== Koma.empty).length; } }