Riichi/frontend/js/game.js
2026-03-13 22:55:41 +01:00

194 lines
4.6 KiB
JavaScript

import "./tile.js";
class Group {
constructor(tiles, stollenTile = null, dir = null) {
this.tiles = tiles;
this.stollenTile = stollenTile;
this.dir = dir; // 1 for left, 2 for middle, 3 for right
}
}
class Hand {
constructor(tiles = []) {
this.tiles = tiles;
this.groups = [];
this.drawn= null;
}
drawTile(tile) {
this.drawn = tile;
}
discard(k) {
if (k === this.tiles.length) {
const tile = this.drawn;
this.drawn = null;
return tile;
} else {
const tile = this.tiles[k];
this.tiles.splice(k, 1);
return tile;
}
}
sort() {
this.tiles.sort((a, b) => {
if (a.lessThan(b)) return -1;
if (b.lessThan(a)) return 1;
return 0;
});
}
flatten() {
if (this.drawn) {
this.tiles.push(this.drawn);
}
this.drawn = null;
this.sort();
}
makeGroup(tiles, stollenTile = null, dir = null) {
const group = new Group(tiles, stollenTile, dir);
this.groups.push(group);
for (let tile of tiles) {
const index = this.tiles.findIndex(t => t.equals(tile));
if (index !== -1) {
this.tiles.splice(index, 1);
}
}
this.flatten();
}
}
class Draw {
constructor() {
this.tiles = Tile.generateAll();
this.shuffle();
}
shuffle() {
for (let i = this.tiles.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this.tiles[i], this.tiles[j]] = [this.tiles[j], this.tiles[i]];
}
}
drawTile() {
return this.tiles.pop();
}
drawHand() {
const handTiles = [];
for (let i = 0; i < 13; i++) {
handTiles.push(this.drawTile());
}
return new Hand(handTiles);
}
}
class Discard {
constructor() {
this.tiles = [];
this.hiddenTiles = [];
}
add(tile) {
this.tiles.push(tile);
}
beeingStollen() {
this.hiddenTiles.push(this.tiles.pop());
return this.hiddenTiles[this.hiddenTiles.length - 1];
}
isIn(tile) {
return this.tiles.some(t => t.equals(tile)) || this.hiddenTiles.some(t => t.equals(tile));
}
}
class Game {
constructor() {
this.discards = [
new Discard(),
new Discard(),
new Discard(),
new Discard()
];
this.wall = new Draw();
this.hands = [
this.wall.drawHand(),
this.wall.drawHand(),
this.wall.drawHand(),
this.wall.drawHand()
];
for (let hand of this.hands) {
hand.sort();
}
this.firstDealer = Math.floor(Math.random() * 4) * 0;
this.turn = this.firstDealer;
this.repeat = 0;
this.draw(this.turn);
}
newDeal(hasRepeat = false) {
this.discards = [
new Discard(),
new Discard(),
new Discard(),
new Discard()
];
this.wall = new Draw();
this.hands = [
this.wall.drawHand(),
this.wall.drawHand(),
this.wall.drawHand(),
this.wall.drawHand()
];
if (!hasRepeat) {
this.turn = (this.firstDealer + 1) % 4;
} else {
this.repeat++;
}
}
nextTurn() {
this.turn = (this.turn + 1) % 4;
}
draw(player) {
this.hands[player].drawTile(this.wall.drawTile());
}
discard(player, k) {
if (player === this.turn) {
const tile = this.hands[player].discard(k);
this.discards[player].add(tile);
this.hands[player].flatten();
}
}
chii(player, tiles, dir) {
const hand = this.hands[player];
dir = (player - this.turn) % 4;
console.assert(dir == 1);
this.hands[player].makeGroup(tiles, this.discards[player].beingStollen(), dir);
}
pon(player, tiles, dir) {
const hand = this.hands[player];
dir = (player - this.turn) % 4;
console.assert(dir == 1);
this.hands[player].makeGroup(tiles, this.discards[player].beingStollen(), dir);
}
botPlay() {
this.draw(this.turn);
const hand = this.hands[this.turn];
const randomIndex = Math.floor(Math.random() * (hand.tiles.length + (hand.drawn ? 1 : 0)));
this.discard(this.turn, randomIndex);
}
}
export { Discard, Draw, Game, Group, Hand };