card_svr/src/utils/assistant.util.ts
2021-03-12 12:32:09 +08:00

339 lines
9.8 KiB
TypeScript

import { Card } from '../rooms/schema/Card'
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'
import { PlayerStateConst } from '../constants/PlayerStateConst'
import { Pet } from '../rooms/schema/Pet'
import { getRandom } from './number.util'
function pushMapVal(map: Map<number, Card[]>, key: number, value: Card) {
if (map.has(key)) {
let arr = map.get(key)
arr.push(value)
map.set(key, arr)
} else {
map.set(key, [value])
}
}
let assistantUtil = {
/**
* 检查是否可以吃牌或出连牌
* @param cardArr 待检查的卡组
* @param card 目标牌
*/
checkDiscard({cardArr, card, rate}: {cardArr: Card[], card?: Card, rate?: number}): {cards: Card[], nums?: number[]} {
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
}
pushMapVal(pointMap, c.number, c)
cardIdSet.add(c.number)
}
if (card && (card.type == CardType.general || card.type == CardType.variable_unit)) {
pushMapVal(pointMap, card.number, card)
cardIdSet.add(card.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 {cards: 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[tmp.length - 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 {cards: result}
} else {
if (cardArr.length > maxCount && rate > 0) {
let random = getRandom(0, 100)
robotLog(`check cheat ^_^ random: ${random}, rate: ${rate}`)
if (random <= rate) {
let max = Math.min(maxCount+2, cardArr.length + 1)
let randomCount = getRandom(maxCount, max)
let resultCards: Card[] = cardArr.randomGet(randomCount)
let sameVal = false
if (getRandom(0, 100) > 50) {
sameVal = true
}
let resultNums = []
if (card && (card.type == CardType.general || card.type == CardType.variable_unit)) {
if (sameVal) {
for (let _c of resultCards) {
resultNums.push(card.number)
}
} else {
resultNums.push(card.number)
for (let _c of resultCards) {
let nextU: number = Math.max.apply(this, resultNums) + 1
let nextD: number = Math.min.apply(this, resultNums) - 1
if (getRandom(0, 100) > 50 ) {
if (nextU <= 10) {
resultNums.push(nextU)
} else {
resultNums.push(nextD)
}
} else {
if (nextD > 0) {
resultNums.push(nextD)
} else {
resultNums.push(nextU)
}
}
}
}
resultCards.push(card)
} else {
if (sameVal) {
for (let i = 0; i < resultCards.length; i++) {
resultNums.push(resultCards[0].number)
}
} else {
resultNums.push(resultCards[0].number)
for (let i = 1; i < resultCards.length; i++) {
let nextU: number = Math.max.apply(this, resultNums) + 1
let nextD: number = Math.min.apply(this, resultNums) - 1
if (getRandom(0, 100) > 50 ) {
if (nextU <= 10) {
resultNums.push(nextU)
} else {
resultNums.push(nextD)
}
} else {
if (nextD > 0) {
resultNums.push(nextD)
} else {
resultNums.push(nextU)
}
}
}
}
return {cards: resultCards, nums: resultNums}
}
}
}
return {cards: [cardArr.randomOne()]}
}
},
/**
* 随机获取敌对玩家
* @private
*/
getEnemyPlayer(dstPlayer: Player, state: CardGameState): Player {
let enemys = []
for (let [, player] of state.players) {
if (player.team !== dstPlayer.team) {
enemys.push(player)
}
}
return enemys.randomOne()
},
/**
* 随机获取可用的随从
* @param player
* @private
*/
getRandomPet(player: Player): number {
if (player.state === PlayerStateConst.PLAYER_DEAD) {
return -1
}
let pets = []
for (let [, pet] of player.pets) {
if (pet.ap > 0 && pet.state == 1)
pets.push(pet)
}
let result: Pet
if (pets.length > 0) {
result = pets.randomOne()
}
return result ? result.pos : 0
},
/**
* 选择一个法术或者一个随从
* @private
*/
async selectPet(dstPlayer: Player, state: CardGameState) {
let cards = [...dstPlayer.cardQueue.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) {
if (dstPlayer.unitCfgs.has(card.effect + '')) {
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
}
let targetType: SkillTargetType = CfgMan.getTargetByCard(result.effect)
robotLog(`select_pet ${ dstPlayer.id }: ${ result.effect } 类型: ${ effectMap.get(result.effect).type_id == EffectType.skill ? '法术' : '随从' }, targetType: ${ targetType }`)
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: HeroCfg = heroArr.randomOne()
return { heroId: hero.id }
}
}
export default assistantUtil