133 lines
3.1 KiB
TypeScript
133 lines
3.1 KiB
TypeScript
import {ALL_RANKS, ALL_SUITS, CARD_VALUES, ENEMY_COUNT, FACE_CARDS} from "@/samples/regicide/constants";
|
|
import {CardRank, Enemy, RegicideCard, SuitType} from "@/samples/regicide/types";
|
|
import {RNG} from "@/utils/rng";
|
|
|
|
/**
|
|
* 获取卡牌面值
|
|
*/
|
|
export function getCardValue(rank: CardRank): number {
|
|
return CARD_VALUES[rank];
|
|
}
|
|
|
|
/**
|
|
* 创建卡牌部件
|
|
*/
|
|
export function createCard(id: string, suit: SuitType, rank: CardRank): RegicideCard {
|
|
return {
|
|
id,
|
|
regionId: '',
|
|
position: [],
|
|
suit,
|
|
rank,
|
|
value: getCardValue(rank),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建敌人
|
|
*/
|
|
export function createEnemy(id: string, rank: CardRank, suit: SuitType): Enemy {
|
|
const value = getCardValue(rank);
|
|
return {
|
|
id,
|
|
rank,
|
|
suit,
|
|
value,
|
|
hp: value * 2,
|
|
maxHp: value * 2,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 生成完整卡牌列表(52张,不含大小王)
|
|
*/
|
|
export function createAllCards(): Record<string, RegicideCard> {
|
|
const cards: Record<string, RegicideCard> = {};
|
|
|
|
for (const suit of ALL_SUITS) {
|
|
for (const rank of ALL_RANKS) {
|
|
const id = `${suit}_${rank}`;
|
|
cards[id] = createCard(id, suit, rank);
|
|
}
|
|
}
|
|
|
|
return cards;
|
|
}
|
|
|
|
/**
|
|
* 构建敌人牌堆(J/Q/K 共12张)
|
|
* 规则:4张K在最下,4张Q在中间,4张J在最上
|
|
*/
|
|
export function buildEnemyDeck(rng: RNG): Enemy[] {
|
|
const enemies: Enemy[] = [];
|
|
let idCounter = 0;
|
|
|
|
// 创建所有J/Q/K敌人
|
|
for (const rank of FACE_CARDS) {
|
|
for (const suit of ALL_SUITS) {
|
|
const id = `enemy_${idCounter++}`;
|
|
enemies.push(createEnemy(id, rank, suit));
|
|
}
|
|
}
|
|
|
|
// 分离J、Q、K
|
|
const jEnemies = enemies.filter(e => e.rank === 'J');
|
|
const qEnemies = enemies.filter(e => e.rank === 'Q');
|
|
const kEnemies = enemies.filter(e => e.rank === 'K');
|
|
|
|
// 分别洗牌
|
|
shuffleArray(jEnemies, rng);
|
|
shuffleArray(qEnemies, rng);
|
|
shuffleArray(kEnemies, rng);
|
|
|
|
// J在最上(先遇到),Q在中间,K在最下
|
|
return [...jEnemies, ...qEnemies, ...kEnemies];
|
|
}
|
|
|
|
/**
|
|
* 构建酒馆牌堆(移除J/Q/K后的剩余牌)
|
|
*/
|
|
export function buildTavernDeck(rng: RNG): RegicideCard[] {
|
|
const allCards = createAllCards();
|
|
const numberCards = Object.values(allCards).filter(card => !FACE_CARDS.includes(card.rank));
|
|
|
|
shuffleArray(numberCards, rng);
|
|
|
|
return numberCards;
|
|
}
|
|
|
|
/**
|
|
* 洗牌辅助函数
|
|
*/
|
|
function shuffleArray<T>(array: T[], rng: RNG): void {
|
|
for (let i = array.length - 1; i > 0; i--) {
|
|
const j = rng.nextInt(i + 1);
|
|
[array[i], array[j]] = [array[j], array[i]];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 从牌堆抽牌
|
|
*/
|
|
export function drawFromDeck(
|
|
deck: RegicideCard[],
|
|
count: number
|
|
): RegicideCard[] {
|
|
const drawn = deck.splice(0, count);
|
|
return drawn;
|
|
}
|
|
|
|
/**
|
|
* 检查敌人是否被击败
|
|
*/
|
|
export function isEnemyDefeated(enemy: Enemy | null): boolean {
|
|
return enemy !== null && enemy.hp <= 0;
|
|
}
|
|
|
|
/**
|
|
* 获取当前玩家手牌区域ID
|
|
*/
|
|
export function getPlayerHandRegionId(playerId: string): string {
|
|
return `hand_${playerId}`;
|
|
}
|