Riichi/src/yakus/yaku.ts

576 lines
8.4 KiB
TypeScript

import { Hand } from "../hand";
import { Group } from "../group";
function ord(g: Group): boolean {
return g.getTiles().every(
t => t.getFamily() < 4 &&
t.getValue() > 1 &&
t.getValue() < 9
)
}
function term(g: Group): boolean {
return g.getTiles().every(
t =>
t.getFamily() < 4 &&
(t.getValue() === 0 ||
t.getValue() === 9)
);
}
function honn(g: Group): boolean {
return g.getTiles().every(
t =>
t.getFamily() >= 4
);
}
function chii(g: Group): boolean {
let t = g.getTiles();
return t[0].getValue() !== t[1].getValue();
}
function pon(g: Group): boolean {
let t = g.getTiles();
return t[0].getValue() === t[1].getValue();
}
export const yakus = {
lipekou: function (
/**
* double suite pure
* 0/1
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
if (groups.length > 0 && !yakus.ryanpeikou(hand, groups, wind)) { // ouvert
return 0;
}
let gr = hand.toGroup() as NonNullable<Array<Group>>;
gr.sort((g1, g2) => g1.compare(g2));
for (let i = 0; i < 3; i++) {
let g1 = gr[i].getTiles();
let g2 = gr[i+1].getTiles();
if (
g1[0].isEqual(g2[0].getFamily(), g2[0].getValue()) &&
chii(gr[i]) && chii(gr[i+1])
) {
return 1;
}
}
return 0;
},
ryanpeikou: function (
/**
* deux doubles suites pures
* 0/3
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
if (groups.length > 0) {
return 0;
}
let gr = hand.toGroup() as NonNullable<Array<Group>>;
gr.filter(g => chii(g));
if (gr.length < 4) { // pas assez de suite
return 0;
}
gr.sort((g1, g2) => g1.compare(g2));
let t1 = gr[0].getTiles()[0];
let t2 = gr[1].getTiles()[0];
let t3 = gr[2].getTiles()[0];
let t4 = gr[3].getTiles()[0];
if (
t1.compare(t2) === 0 &&
t3.compare(t4) === 0
) {
return 3;
}
return 0;
},
pinfu: function(
/**
* tout suite
* 0/1
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number { //TODO: double attente
if (groups.length > 0) {
return 0;
}
let h = hand.toGroup();
if (
h !== undefined &&
h.every(
g => {
let tiles = g.getTiles();
return (chii(g) || tiles.length === 2)
}
)
) {
return 1;
}
return 0;
},
sanshokuDoujun: function( // TODO
/**
* triple suite
* 1/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
let gr;
if (h !== undefined) {
gr = groups.concat(h);
} else {
gr = groups;
}
gr = gr.filter(g => chii(g));
gr.sort((g1, g2) => g1.compare(g2))
if (gr.length < 3) { // pas assez de chii
return 0;
} else if(gr.length === 3) {
let t0 = gr[0].getTiles();
let t1 = gr[1].getTiles();
let t2 = gr[2].getTiles();
if (
t0[0].getValue() === t1[0].getValue() &&
t0[0].getValue() === t2[0].getValue() &&
t0[0].getFamily() !== t1[0].getFamily() &&
t0[0].getFamily() !== t2[0].getFamily() &&
t1[0].getFamily() !== t2[0].getFamily()
) {
return groups.length > 0 ? 1 : 2;
}
return 0;
} else {// il y a un intrus
return 1
}
},
ittsuu: function(
/**
* grande suite pure
* 1/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let gr = groups.concat(hand.toGroup() as NonNullable<Array<Group>>);
gr.sort((g1, g2) => g1.compare(g2));
gr.filter(g => chii(g));
if (gr.length < 3) { // trop peu de suite
return 0;
} else if (gr.length === 3) { // pile le bon nombre
let g1 = gr[0].getTiles();
let g2 = gr[1].getTiles();
let g3 = gr[2].getTiles();
if (
g1[0].getFamily() === g2[0].getFamily() &&
g2[0].getFamily() === g3[0].getFamily() &&
g1[0].getValue() === 1 &&
g2[0].getValue() === 4 &&
g3[0].getValue() === 7
) {
return groups.length > 0 ? 1 : 2;
}
} else { // il y a un intrus
return 0 //TODO
}
return 0;
},
tanyao: function(
/**
* tout ordinaire
* 1/1
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
if (h === undefined) {
return 0;
}
if (
groups.every(g => ord(g)) &&
h.every(g => ord(g))
) {
return 1;
}
return 0;
},
yakuhai: function(
/**
* brelan de valeur
* 1/1
*/
// TODO multiplicité !
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
shousangen: function( //TODO
/**
* trois petits dragons
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
daisangen: function( //TODO
/**
* trois grands dragons
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
shousuushii: function( //TODO
/**
* quatre petits vents
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
daisuushi: function( //TODO
/**
* quatre grands vents
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
chanta: function( //TODO
/**
* terminales et honneurs partout
* 1/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
junchan: function( //TODO
/**
* terminales partout
* 2/3
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
honroutou: function( //TODO
/**
* tout terminale et honneur
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
chinroutou: function(
/**
* tout terminale
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
if (h === undefined) {
return 0;
}
if (
groups.every(g => term(g)) &&
h.every(g => term(g))
) {
return 13;
}
return 0;
},
tsuuiisou: function(
/**
* tout honneur
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
if (h === undefined) {
return 0;
}
if (
groups.every(g => honn(g)) &&
h.every(g => honn(g))
) {
return 13;
}
return 0;
},
kokushiMusou: function(
/**
* treize orphelins
* 0/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
if (groups.length > 0) {
return 0;
}
if (yakus.honroutou(hand, groups, wind) === 0) {
return 0;
}
let h = hand.getTiles();
let count = 0;
for (let i = 0; i < h.length - 1; i++) {
if (h[i].isEqual(h[i+1].getFamily(), h[i+1].getValue())) {
count++;
}
if (count > 1) {
break;
}
}
if (count === 1) {
return 13;
}
return 0;
},
chiitoitsu: function(
/**
* sept paires
* 0/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
if (groups.length > 0) {
return 0;
}
//TODO
},
toitoi: function(
/**
* tout brelans
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
if (
groups.every(g => pon(g)) &&
h?.every(g => pon(g))
) {
return 2;
}
return 0;
},
sanankou: function(
/**
* trois brelan cachés
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
let count = 0;
h?.forEach(
g => {
if (pon(g) && g.getTiles().length === 3) {
count++;
}
}
);
if (count === 3) {
return 2;
}
return 0;
},
suuankou: function(
/**
* quatre brelans cachés
* 0/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.toGroup();
let count = 0;
h?.forEach(
g => {
if (pon(g) && g.getTiles().length === 3) {
count++;
}
}
);
if (count === 4) {
return 13;
}
return 0;
},
sanshokuDoukou: function( //TODO
/**
* triple brelan
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
sankantsu: function( //TODO
/**
* trois carrés
* 2/2
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
suukantsu: function( //TODO
/**
* quatre carrés
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
honitsu: function( //TODO
/**
* semie pure
* 2/3
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
return 0;
},
chinitsu: function(
/**
* main pure
* 5/6
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
let h = hand.getTiles();
let t0 = h[0];
if (
h.every(t => t.getFamily() === t0.getFamily()) &&
groups.every(g => g.getTiles().every(t => t.getFamily() === t0.getFamily()))
) {
return groups.length > 0 ? 5 : 6;
}
return 0;
},
ryuuisou: function( //TODO
/**
* main verte
* 13/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
if (yakus.chinitsu(hand, groups, wind) === 0) {
return 0;
}
return 0;
},
chuurenPoutou: function( //TODO
/**
* neuf portes
* 0/13
*/
hand: Hand,
groups: Array<Group>,
wind: number
): number {
if (groups.length > 0 || yakus.chinitsu(hand, groups, wind) === 0) {
return 0;
}
return 0;
}
}