258 lines
8.2 KiB
TypeScript
258 lines
8.2 KiB
TypeScript
import {Card} from "../rooms/schema/Card";
|
|
import arrUtil from "./array.util";
|
|
import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg";
|
|
import {BaseConst} from "../constants/BaseConst";
|
|
import {SkillTargetType} from "../rooms/logic/skill/SkillConst";
|
|
import CfgMan from "../rooms/logic/CfgMan";
|
|
import {CardGameState} from "../rooms/schema/CardGameState";
|
|
import {Player} from "../rooms/schema/Player";
|
|
import {HeroCfg} from "../cfg/parsers/HeroCfg";
|
|
import {EffectType} from "../cfg/enums/EffectType";
|
|
import {CardType} from "../cfg/enums/CardType";
|
|
import {GameEnv} from "../cfg/GameEnv";
|
|
import {error, robotLog} from "../common/Debug";
|
|
|
|
let assistantUtil = {
|
|
|
|
/**
|
|
* 检查是否可以吃牌
|
|
* @param cardArr 待检查的卡组
|
|
* @param card 目标牌
|
|
*/
|
|
checkTriple(cardArr: Card[], card?: Card): Card[] {
|
|
if (card) cardArr.push(card);
|
|
let maxCount = card ? new GameEnv().otherEatCount : new GameEnv().selfEatCount;
|
|
let pointMap: Map<number, Card[]> = new Map();
|
|
let cardIdSet: Set<number> = new Set();
|
|
for (let c of cardArr) {
|
|
if (!(c.type == CardType.general || c.type == CardType.variable_unit)) {
|
|
continue;
|
|
}
|
|
if (pointMap.has(c.number)) {
|
|
let arr = pointMap.get(c.number);
|
|
arr.push(c);
|
|
pointMap.set(c.number, arr);
|
|
} else {
|
|
pointMap.set(c.number, [c]);
|
|
}
|
|
cardIdSet.add(c.number);
|
|
}
|
|
let fetched = false;
|
|
let result: Card[] = [];
|
|
// 优先出对子
|
|
for (let [point, arr] of pointMap) {
|
|
if (card) {
|
|
if (point == card.number && arr.length >= maxCount) {
|
|
fetched = true;
|
|
result = arr;
|
|
break;
|
|
}
|
|
} else {
|
|
if (arr.length >= maxCount) {
|
|
fetched = true;
|
|
result = arr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (fetched) {
|
|
return result;
|
|
}
|
|
|
|
let cardIds = [...cardIdSet];
|
|
cardIds.sort((a, b) => a - b);
|
|
let tmp = [];
|
|
for (let i = 0, length = cardIds.length; i < length; i++) {
|
|
let cur = cardIds[i];
|
|
i == 0 && tmp.push(cur);
|
|
if (i > 0) {
|
|
if (cur != tmp[i - 1] + 1) {
|
|
tmp.length = 0;
|
|
}
|
|
tmp.push(cur);
|
|
}
|
|
if (card) {
|
|
if (tmp.indexOf(card.number) >= 0 && tmp.length >= maxCount) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (tmp.length >= maxCount) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tmp.length >= maxCount) {
|
|
let subTmp = [];
|
|
for (let i = tmp[0] - 1; i > 0; i--) {
|
|
if (cardIdSet.has(i)) {
|
|
subTmp.push(i);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
for (let i = tmp[tmp.length]; i < cardIdSet.size; i++) {
|
|
if (cardIdSet.has(i)) {
|
|
subTmp.push(i);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
tmp = tmp.concat(subTmp);
|
|
for (let point of tmp) {
|
|
if (card && point === card.number) {
|
|
result.push(card);
|
|
} else {
|
|
result.push(pointMap.get(point)[0]);
|
|
}
|
|
}
|
|
return result;
|
|
} else {
|
|
return arrUtil.randomGet(cardArr, 1);
|
|
}
|
|
},
|
|
/**
|
|
* 随机获取敌对玩家
|
|
* @private
|
|
*/
|
|
getEnemyPlayer(dstPlayer: Player, state: CardGameState): Player {
|
|
let enemys = [];
|
|
for (let [, player] of state.players) {
|
|
if (player.team !== dstPlayer.team) {
|
|
enemys.push(player);
|
|
}
|
|
}
|
|
return arrUtil.randomOne(enemys);
|
|
},
|
|
|
|
/**
|
|
* 随机获取可用的随从
|
|
* @param player
|
|
* @private
|
|
*/
|
|
getRandomPet(player: Player): number {
|
|
let pets = [];
|
|
for (let [, pet] of player.pets) {
|
|
if (pet.ap > 0 && pet.state == 1)
|
|
pets.push(pet);
|
|
}
|
|
let result;
|
|
if (pets.length > 0) {
|
|
result = arrUtil.randomOne(pets);
|
|
}
|
|
return result ? result.pos : -1;
|
|
},
|
|
/**
|
|
* 选择一个法术或者一个随从
|
|
* @private
|
|
*/
|
|
async selectPet(dstPlayer: Player, state: CardGameState) {
|
|
let cards = [...state.cards.values()];
|
|
let result: Card;
|
|
let effectMap: Map<number, EffectCardCfg> = global.$cfg.get(BaseConst.EFFECTCARD);
|
|
let spellCards: Card[] = [];
|
|
let petCards: Card[] = [];
|
|
|
|
// 优先取随从
|
|
let petCount = 0;
|
|
for (let [,pet] of dstPlayer.pets) {
|
|
if (pet.state == 1 && !pet.isHero) petCount ++;
|
|
}
|
|
let noMorePet = petCount >= new GameEnv().maxPlayerPetCount;
|
|
|
|
let noPet = Math.random2(0, 100) > 70;
|
|
|
|
for (let card of cards) {
|
|
if (card.type == CardType.variable_unit) {
|
|
petCards.push(card);
|
|
} else if (card.type == CardType.general) {
|
|
spellCards.push(card);
|
|
}
|
|
}
|
|
if (!noMorePet && !noPet && petCards.length > 0) {
|
|
result = petCards.randomOne();
|
|
}
|
|
|
|
if (!result && spellCards.length > 0) {
|
|
result = spellCards.randomOne();
|
|
}
|
|
let oldpos = -1;
|
|
if (!result && petCards.length > 0) {
|
|
result = petCards.randomOne();
|
|
if (noMorePet) {
|
|
oldpos = 1;
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
error(`无法选择随从或法术, 随从数: ${petCount}, 法术牌数量: ${spellCards.length}`);
|
|
return null;
|
|
}
|
|
robotLog(`select_pet ${dstPlayer.id}: ${result.effect} 类型: ${effectMap.get(result.effect).type_id == EffectType.skill ? '法术' : '随从'}`)
|
|
let targetType: SkillTargetType = CfgMan.getTargetByCard(result.effect);
|
|
let targetPlayer;
|
|
let targetPos;
|
|
switch (targetType) {
|
|
case SkillTargetType.ENEMY_PLAYER:
|
|
targetPlayer = this.getEnemyPlayer(dstPlayer, state);
|
|
break;
|
|
case SkillTargetType.ENEMY_PET:
|
|
for (let [, player] of state.players) {
|
|
if (player.team !== dstPlayer.team) {
|
|
let pos = this.getRandomPet(player);
|
|
if (pos > -1) {
|
|
targetPlayer = player;
|
|
targetPos = pos;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SkillTargetType.FRIEND_PET:
|
|
for (let [, player] of state.players) {
|
|
if (player.team == dstPlayer.team) {
|
|
let pos = this.getRandomPet(player);
|
|
if (pos > -1) {
|
|
targetPlayer = player;
|
|
targetPos = pos;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SkillTargetType.SELF_PET:
|
|
let pos = this.getRandomPet(dstPlayer);
|
|
if (pos > -1) {
|
|
targetPlayer = dstPlayer;
|
|
targetPos = pos;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
//TODO: 增加效果卡
|
|
let effCards: number[] = [];
|
|
for (let [,card] of dstPlayer.cards) {
|
|
if (card.type == CardType.double_effect || card.type == CardType.double_point) {
|
|
effCards.push(card.id);
|
|
}
|
|
}
|
|
return {
|
|
card: result.id,
|
|
player: targetPlayer?.id,
|
|
pos: targetPos,
|
|
effCards,
|
|
oldpos
|
|
}
|
|
|
|
},
|
|
randomHero() {
|
|
let heroMap: Map<number, HeroCfg> = global.$cfg.get(BaseConst.HERO);
|
|
let heroArr = [...heroMap.values()];
|
|
let hero = arrUtil.randomGet(heroArr, 1);
|
|
return {heroId: hero[0].id}
|
|
}
|
|
}
|
|
|
|
export default assistantUtil;
|