修改机器人出牌逻辑, 增加放弃吃牌和胡牌的机制
This commit is contained in:
parent
984ad01fb3
commit
498a81a3b7
@ -66,18 +66,24 @@ export class GameEnv {
|
||||
public petInheritRate: number
|
||||
// 低级机器人的胜率值
|
||||
public robotLvlLow: number
|
||||
public robotRateLow: number
|
||||
|
||||
// 中等机器人的胜率值
|
||||
public robotLvlMid: number
|
||||
public robotRateMid: number
|
||||
|
||||
// 高级机器人的胜率值
|
||||
public robotLvlHigh: number
|
||||
public robotRateHigh: number
|
||||
|
||||
// 变态机器人的胜率值
|
||||
public robotLvlExtra: number
|
||||
public robotRateExtra: number
|
||||
|
||||
|
||||
// 电脑作弊机率
|
||||
public robotCheatRate: number[]
|
||||
// 电脑放弃吃牌机率
|
||||
public robotNoEatRate: number[]
|
||||
// 电脑放弃胡牌机率
|
||||
public robotNoTripleRate: number[]
|
||||
|
||||
// 等待玩家确认的最长时间
|
||||
public maxWaitingTime: number
|
||||
|
||||
@ -121,21 +127,54 @@ export class GameEnv {
|
||||
this.robotLvlMid = parseInt(data.get(BaseConst.ROBOT_LVL_MID).value)
|
||||
this.robotLvlHigh = parseInt(data.get(BaseConst.ROBOT_LVL_HIGHT).value)
|
||||
this.robotLvlExtra = parseInt(data.get(BaseConst.ROBOT_LVL_EXTRA).value)
|
||||
this.robotRateLow = parseInt(data.get(BaseConst.ROBOT_RATE_LOW).value)
|
||||
this.robotRateMid = parseInt(data.get(BaseConst.ROBOT_RATE_MID).value)
|
||||
this.robotRateHigh = parseInt(data.get(BaseConst.ROBOT_RATE_HIGHT).value)
|
||||
this.robotRateExtra = parseInt(data.get(BaseConst.ROBOT_RATE_EXTRA).value)
|
||||
this.robotCheatRate = [
|
||||
+data.get(BaseConst.ROBOT_RATE_LOW).value,
|
||||
+data.get(BaseConst.ROBOT_RATE_MID).value,
|
||||
+data.get(BaseConst.ROBOT_RATE_HIGHT).value,
|
||||
+data.get(BaseConst.ROBOT_RATE_EXTRA).value
|
||||
]
|
||||
this.robotNoEatRate = [
|
||||
+(data.get(99053)?.value || 0) ,
|
||||
+(data.get(99054)?.value || 0),
|
||||
+(data.get(99055)?.value || 0),
|
||||
+(data.get(99056)?.value || 0),
|
||||
]
|
||||
this.robotNoTripleRate = [
|
||||
+(data.get(99057)?.value || 0),
|
||||
+(data.get(99058)?.value || 0),
|
||||
+(data.get(99059)?.value || 0),
|
||||
+(data.get(99060)?.value || 0),
|
||||
]
|
||||
this.maxWaitingTime = 60
|
||||
}
|
||||
public getCheatRate(val: number) {
|
||||
if (val < this.robotRateMid) {
|
||||
return this.robotRateLow
|
||||
|
||||
/**
|
||||
* 获取机器人配置
|
||||
* @param {number} lvl
|
||||
* @return {{noEatRate: number, lvl: number, cheatRate: number, noTripleRate: number}}
|
||||
*/
|
||||
public getRobotCfg(lvl: number) {
|
||||
const cheatRate = this.robotCheatRate[lvl] || 0
|
||||
const noEatRate = this.robotNoEatRate[lvl] || 0
|
||||
const noTripleRate = this.robotNoTripleRate[lvl] || 0
|
||||
return {lvl, cheatRate, noEatRate, noTripleRate}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定机器人等级
|
||||
* @param {number} val 玩家十场胜率
|
||||
* @return {number}
|
||||
*/
|
||||
public getRobotLvl(val: number) {
|
||||
if (val < this.robotLvlMid) {
|
||||
return 0
|
||||
} if (val < this.robotLvlHigh) {
|
||||
return this.robotRateMid
|
||||
return 1
|
||||
} else if (val < this.robotLvlExtra) {
|
||||
return this.robotRateHigh
|
||||
} else if (val >= this.robotRateExtra){
|
||||
return this.robotRateExtra
|
||||
return 2
|
||||
} else if (val >= this.robotLvlExtra){
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export class RoomOptions {
|
||||
* @param opt
|
||||
*/
|
||||
public multipleEat(opt?: any) {
|
||||
return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import { Player } from '../rooms/schema/Player'
|
||||
import assistantUtil from '../utils/assistant.util'
|
||||
import { delay, wait } from '../decorators/cfg'
|
||||
import { RULE_CANEAT } from '../cfg/RoomOptions'
|
||||
import { GameEnv } from '../cfg/GameEnv'
|
||||
|
||||
export class Robot {
|
||||
host: string
|
||||
@ -15,6 +16,9 @@ export class Robot {
|
||||
myTurn: boolean = false
|
||||
player: Player
|
||||
cheatRate: number = 0
|
||||
noEatRate: number = 0
|
||||
noTripleRate: number = 0
|
||||
lvl: number = 0
|
||||
|
||||
constructor(host: string, roomId: string) {
|
||||
this.host = host
|
||||
@ -65,9 +69,13 @@ export class Robot {
|
||||
self.selectPet()
|
||||
}
|
||||
break
|
||||
case 'update_change_rate':
|
||||
log(`update cheat rate to: ${data.val}`)
|
||||
self.cheatRate = data.val
|
||||
case 'update_robot_level':
|
||||
const { cheatRate, noEatRate, noTripleRate } = new GameEnv().getRobotCfg(data.lvl)
|
||||
log(`update robot lvl to: ${data.lvl}, cheatRate: ${cheatRate}, noEatRate: ${noEatRate}, noTripleRate: ${noTripleRate}`)
|
||||
this.lvl = data.lvl
|
||||
this.cheatRate = cheatRate
|
||||
this.noEatRate = noEatRate
|
||||
this.noTripleRate = noTripleRate
|
||||
break
|
||||
}
|
||||
})
|
||||
@ -175,11 +183,13 @@ export class Robot {
|
||||
}
|
||||
let self = this
|
||||
let cardArr = [...self.player.cards.values()]
|
||||
let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate})
|
||||
let result = assistantUtil.discard({cardArr, eatCard: targetCard, rate: this.cheatRate, noEatRate: this.noEatRate, noTripleRate: this.noTripleRate})
|
||||
let cards = result.cards;
|
||||
if (!cards || cards.length == 0) {
|
||||
return
|
||||
}
|
||||
// for test
|
||||
// cards = cardArr.randomGet(1)
|
||||
let cardIds: number[] = []
|
||||
let hasEatCard = false
|
||||
for (let card of cards) {
|
||||
@ -205,13 +215,14 @@ export class Robot {
|
||||
|
||||
/**
|
||||
* 吃牌或者放弃
|
||||
* 这个方法逻辑已经有问题了, 暂时没用, 如果需要时, 须更改
|
||||
* @private
|
||||
*/
|
||||
@wait('maxEatTime')
|
||||
private async eatOrGiveUp() {
|
||||
let targetCard = [...this.room.state.cards.values()][0]
|
||||
let cardArr = [...this.player.cards.values()]
|
||||
let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate})
|
||||
let result = assistantUtil.discard({cardArr, eatCard: targetCard, rate: this.cheatRate, noEatRate: this.noEatRate, noTripleRate: this.noTripleRate})
|
||||
let tmpCards = result.cards;
|
||||
let next = this.giveup.bind(this)
|
||||
if (tmpCards.length > 1 && targetCard.type === 1) {
|
||||
|
@ -9,6 +9,7 @@ import { Player } from '../rooms/schema/Player'
|
||||
import assistantUtil from '../utils/assistant.util'
|
||||
import { wait } from '../decorators/cfg'
|
||||
import { RULE_CANEAT } from '../cfg/RoomOptions'
|
||||
import { GameEnv } from '../cfg/GameEnv'
|
||||
|
||||
/**
|
||||
* 服务端辅助机器人
|
||||
@ -32,6 +33,9 @@ export class RobotClient implements Client {
|
||||
listenerTurn: any
|
||||
active: boolean = false
|
||||
cheatRate: number = 0
|
||||
noEatRate: number = 0
|
||||
noTripleRate: number = 0
|
||||
lvl: number = 0
|
||||
|
||||
constructor(sessionId: string, state: CardGameState, onMessageHandlers: { [id: string]: (client: Client, message: any) => void }) {
|
||||
this.sessionId = sessionId
|
||||
@ -87,10 +91,15 @@ export class RobotClient implements Client {
|
||||
self.selectPet()
|
||||
}
|
||||
break
|
||||
case 'update_change_rate':
|
||||
log(`update cheat rate to: ${data.val}`)
|
||||
self.cheatRate = data.val
|
||||
case 'update_robot_level':
|
||||
const { cheatRate, noEatRate, noTripleRate } = new GameEnv().getRobotCfg(data.lvl)
|
||||
log(`update robot lvl to: ${data.lvl}, cheatRate: ${cheatRate}, noEatRate: ${noEatRate}, noTripleRate: ${noTripleRate}`)
|
||||
this.lvl = data.lvl
|
||||
this.cheatRate = cheatRate
|
||||
this.noEatRate = noEatRate
|
||||
this.noTripleRate = noTripleRate
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +161,7 @@ export class RobotClient implements Client {
|
||||
}
|
||||
let self = this
|
||||
let cardArr = [...self.selfPlayer.cards.values()]
|
||||
let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate})
|
||||
let result = assistantUtil.discard({cardArr, eatCard: targetCard, rate: this.cheatRate, noEatRate: this.noEatRate, noTripleRate: this.noTripleRate})
|
||||
let cards = result.cards
|
||||
if (!cards || cards.length == 0) {
|
||||
return
|
||||
@ -182,13 +191,14 @@ export class RobotClient implements Client {
|
||||
|
||||
/**
|
||||
* 吃牌或者放弃
|
||||
* 这个方法逻辑已经有问题了, 暂时没用, 如果需要时, 须更改
|
||||
* @private
|
||||
*/
|
||||
@wait('maxEatTime')
|
||||
private async eatOrGiveUp() {
|
||||
let targetCard = [...this.svrstate.cards.values()][0]
|
||||
let cardArr = [...this.selfPlayer.cards.values()]
|
||||
let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate})
|
||||
let result = assistantUtil.discard({cardArr, eatCard: targetCard, rate: this.cheatRate, noEatRate: this.noEatRate, noTripleRate: this.noTripleRate})
|
||||
let tmpCards = result.cards
|
||||
let next = this.giveup.bind(this)
|
||||
if (tmpCards.length > 1 && targetCard.type === 1) {
|
||||
|
@ -44,12 +44,10 @@ export class BeginGameCommand extends Command<CardGameState, {}> {
|
||||
}
|
||||
|
||||
let assistClient = this.room.getAssistClient(player.id)
|
||||
let rate = new GameEnv().getCheatRate(oplayer.winRate * 100)
|
||||
if (rate) {
|
||||
debugRoom(`opposite play win rate: ${ oplayer.winRate }, robot cheat rate: ${ rate }`)
|
||||
client.send('update_change_rate', { val: rate })
|
||||
assistClient.send('update_change_rate', { val: rate })
|
||||
}
|
||||
let lvl = new GameEnv().getRobotLvl(oplayer.winRate * 100)
|
||||
debugRoom(`opposite play win rate: ${ oplayer.winRate }, robot lvl: ${ lvl }`)
|
||||
client.send('update_robot_level', { lvl })
|
||||
assistClient.send('update_robot_level', { lvl })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,8 @@ export class SelectPetCommand extends Command<CardGameState, {
|
||||
let time = this.room.battleMan.useCard(data)
|
||||
await this.delay(time)
|
||||
const multipEat = !!this.state.rules.get(RULE_MULTIPLEEAT)
|
||||
if (multipEat && assistantUtil.checkDiscard({cardArr: [...player.cards.values()]}).cards.length > 1) {
|
||||
const { selfEat } = assistantUtil.checkDiscard({cardArr: [...player.cards.values()]})
|
||||
if (multipEat && selfEat) {
|
||||
this.state.updateGameState(GameStateConst.STATE_BEGIN_DRAW)
|
||||
this.state.updateGameTurn(player.id, this.state.eatCount + 1)
|
||||
debugRoom(`more eatcount for player ${player.id}, ${this.state.eatCount}`)
|
||||
|
@ -24,169 +24,246 @@ function pushMapVal(map: Map<number, Card[]>, key: number, value: Card) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一组含有特殊点数的豹子牌
|
||||
* @param {Map<number, Card[]>} pointMap
|
||||
* @param {number} special
|
||||
* @return {Card[]}
|
||||
*/
|
||||
function seekPairWithSpecial(pointMap: Map<number, Card[]>, special?: Card) {
|
||||
let minCount = new GameEnv().otherEatCount
|
||||
let result: Card[] = []
|
||||
for (let [point, arr] of pointMap) {
|
||||
if (point == special?.number && arr.length >= minCount) {
|
||||
result = arr
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一组不!!含有特殊点数的豹子牌
|
||||
* @param {Map<number, Card[]>} pointMap
|
||||
* @param {number} special
|
||||
* @return {Card[]}
|
||||
*/
|
||||
function seekPairNoSpecial(pointMap: Map<number, Card[]>, special?: Card) {
|
||||
let minCount = new GameEnv().selfEatCount
|
||||
let result: Card[] = []
|
||||
for (let [point, arr] of pointMap) {
|
||||
if (arr.length >= minCount ) {
|
||||
if (!!special && point !== special?.number) {
|
||||
result = arr
|
||||
break
|
||||
} else if (!special) {
|
||||
result = arr
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 检查顺子
|
||||
* @param pointMap
|
||||
* @param {number[]} points 升序的distinct点数数组
|
||||
* @param {number} special 特殊点数
|
||||
* @param {boolean} hasSpecial true: 必须包含特殊点数
|
||||
* false: 不包含特殊点数,
|
||||
* 如果特殊点数不存在, 那么忽略该值
|
||||
*/
|
||||
function seekSeq(pointMap: Map<number, Card[]>, points: number[], hasSpecial: boolean, special?: Card) {
|
||||
let minLength = special? new GameEnv().otherEatCount : new GameEnv().selfEatCount
|
||||
let tmp: number[] = []
|
||||
for (let i = 0, length = points.length; i < length; i++) {
|
||||
let cur = points[i]
|
||||
if (i > 0) {
|
||||
if ((cur != tmp[tmp.length - 1] + 1)) {
|
||||
if (tmp.length < minLength) {
|
||||
tmp.length = 0
|
||||
} else {
|
||||
if (hasSpecial && !!special && tmp.indexOf(special.number) == -1) {
|
||||
tmp.length = 0
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((!hasSpecial && !!special && cur == special.number) ) {
|
||||
continue
|
||||
}
|
||||
tmp.push(cur)
|
||||
}
|
||||
// 将获取到的点数sequence转换为Card数组
|
||||
let result: Card[] = []
|
||||
if (tmp.length > minLength) {
|
||||
for (let point of tmp) {
|
||||
if (special && point === special.number) {
|
||||
result.push(special)
|
||||
} else {
|
||||
result.push(pointMap.get(point)[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function parseCheat(this: any, cardArr: Card[], rate: number, eatCard?: Card) {
|
||||
let minCount = eatCard ? new GameEnv().otherEatCount : new GameEnv().selfEatCount
|
||||
if (cardArr.length >= minCount && rate > 0) {
|
||||
let random = getRandom(0, 100)
|
||||
robotLog(`check cheat ^_^ random: ${random}, rate: ${rate}`)
|
||||
if (random <= rate) {
|
||||
let max = Math.min(minCount+2, cardArr.length + 1)
|
||||
let randomCount = getRandom(minCount, max)
|
||||
let resultCards: Card[] = cardArr.randomGet(randomCount)
|
||||
let sameVal = false
|
||||
if (getRandom(0, 100) > 50) {
|
||||
sameVal = true
|
||||
}
|
||||
let resultNums = []
|
||||
if (eatCard && (eatCard.type == CardType.general || eatCard.type == CardType.variable_unit)) {
|
||||
if (sameVal) {
|
||||
for (let _c of resultCards) {
|
||||
resultNums.push(eatCard.number)
|
||||
}
|
||||
} else {
|
||||
resultNums.push(eatCard.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(eatCard)
|
||||
} 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}
|
||||
}
|
||||
}
|
||||
const oneCardArr: Card[] = cardArr.randomGet(1)
|
||||
return {cards: oneCardArr }
|
||||
}
|
||||
|
||||
|
||||
let assistantUtil = {
|
||||
|
||||
/**
|
||||
* 检查是否可以吃牌或出连牌
|
||||
* @param cardArr 待检查的卡组
|
||||
* @param card 目标牌
|
||||
* @param eatCard 可以吃的牌
|
||||
* @param rate 作弊机率
|
||||
*/
|
||||
checkDiscard({cardArr, card, rate}: {cardArr: Card[], card?: Card, rate?: number}): {cards: Card[], nums?: number[]} {
|
||||
let maxCount = card ? new GameEnv().otherEatCount : new GameEnv().selfEatCount
|
||||
checkDiscard({cardArr, eatCard }: {cardArr: Card[], eatCard?: Card}): any{
|
||||
let pointMap: Map<number, Card[]> = new Map()
|
||||
let cardIdSet: Set<number> = new Set()
|
||||
let cardPointSet: 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)
|
||||
cardPointSet.add(c.number)
|
||||
}
|
||||
if (card && (card.type == CardType.general || card.type == CardType.variable_unit)) {
|
||||
pushMapVal(pointMap, card.number, card)
|
||||
cardIdSet.add(card.number)
|
||||
if (eatCard && (eatCard.type == CardType.general || eatCard.type == CardType.variable_unit)) {
|
||||
pushMapVal(pointMap, eatCard.number, eatCard)
|
||||
cardPointSet.add(eatCard.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
|
||||
}
|
||||
}
|
||||
let cardPoints = [...cardPointSet]
|
||||
cardPoints.sort((a, b) => a - b)
|
||||
|
||||
let eatPairs = seekPairWithSpecial(pointMap, eatCard)
|
||||
let normalPairs = seekPairNoSpecial(pointMap, eatCard)
|
||||
let eatSecs = seekSeq(pointMap, cardPoints, true, eatCard)
|
||||
let normalSecs = seekSeq(pointMap, cardPoints, false, eatCard)
|
||||
const selfEat = normalPairs.length > 0 || normalSecs.length > 0
|
||||
const otherEat = eatPairs.length > 0 || eatSecs.length > 0
|
||||
return {
|
||||
selfEat,
|
||||
otherEat,
|
||||
eatPairs,
|
||||
normalPairs,
|
||||
eatSecs,
|
||||
normalSecs
|
||||
}
|
||||
if (fetched) {
|
||||
return {cards: result}
|
||||
},
|
||||
/**
|
||||
* 出牌
|
||||
*/
|
||||
discard({cardArr, eatCard, rate, noEatRate, noTripleRate}:
|
||||
{cardArr: Card[],
|
||||
eatCard?: Card,
|
||||
rate: number,
|
||||
noEatRate: number,
|
||||
noTripleRate: number}): {cards: Card[], nums?: number[]} {
|
||||
const {
|
||||
selfEat,
|
||||
otherEat,
|
||||
eatPairs,
|
||||
normalPairs,
|
||||
eatSecs,
|
||||
normalSecs
|
||||
} = this.checkDiscard({cardArr, eatCard})
|
||||
robotLog(`discard check result: selfEat: ${selfEat}, otherEat: ${otherEat}`)
|
||||
let results: Card[] = []
|
||||
let random = getRandom(0, 100)
|
||||
if (otherEat && random <= noEatRate) {
|
||||
robotLog(`cat eat, but random(${random}) less then cfg(${noEatRate})`)
|
||||
} else if (otherEat && random > noEatRate) {
|
||||
results = eatPairs.length > 0? eatPairs : eatSecs
|
||||
robotLog(`eat card random(${random}) cfg(${noEatRate}) ${results.map(o=>o.number)}`)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
random = getRandom(0, 100)
|
||||
if (selfEat && results.length == 0 && random <= noTripleRate) {
|
||||
robotLog(`can hu, but random(${random}) less then cfg(${noTripleRate})`)
|
||||
} if (selfEat && results.length == 0 && random > noTripleRate) {
|
||||
results = normalPairs.length > 0 ? normalPairs : normalSecs
|
||||
robotLog(`hu card random(${random}) cfg(${noTripleRate}) ${results.map(o=>o.number)}`)
|
||||
}
|
||||
|
||||
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()]}
|
||||
if (results.length == 0) {
|
||||
results = cardArr.randomGet(1)
|
||||
}
|
||||
if (!selfEat && !otherEat) {
|
||||
return parseCheat(cardArr, rate, eatCard)
|
||||
}
|
||||
return {cards: results}
|
||||
},
|
||||
/**
|
||||
* 随机获取敌对玩家
|
||||
|
Loading…
x
Reference in New Issue
Block a user