From 579a3dd318337b53d1e32483ba5b2cba3086f728 Mon Sep 17 00:00:00 2001 From: zhl Date: Fri, 5 Mar 2021 18:18:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E7=9A=84=E4=BD=9C=E5=BC=8A=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cfg/GameEnv.ts | 206 +++++++++++++------------ src/constants/BaseConst.ts | 4 + src/global.d.ts | 8 + src/robot/Robot.ts | 14 +- src/robot/RobotClient.ts | 14 +- src/rooms/GeneralRoom.ts | 15 +- src/rooms/commands/BeginGameCommand.ts | 47 +++++- src/rooms/commands/DiscardCommand.ts | 16 +- src/rooms/commands/OnJoinCommand.ts | 82 +++++----- src/rooms/commands/SelectPetCommand.ts | 2 +- src/rooms/schema/Player.ts | 5 +- src/utils/assistant.util.ts | 76 ++++++++- src/utils/game.util.ts | 13 ++ 13 files changed, 346 insertions(+), 156 deletions(-) diff --git a/src/cfg/GameEnv.ts b/src/cfg/GameEnv.ts index 3b30000..675612c 100644 --- a/src/cfg/GameEnv.ts +++ b/src/cfg/GameEnv.ts @@ -1,105 +1,111 @@ -import {BaseCfg} from "./parsers/BaseCfg"; -import {BaseConst} from "../constants/BaseConst"; -import {singleton} from "../decorators/singleton.decorator"; +import { BaseCfg } from './parsers/BaseCfg' +import { BaseConst } from '../constants/BaseConst' +import { singleton } from '../decorators/singleton.decorator' @singleton export class GameEnv { - // 初始手牌数量 - public initCardNum: number; - // 可更换的初始手牌上限 - public cardChangeNum : number; - // 更换初始手牌时限 - public cardChangeTime: number; - // 每回合发牌数量 - public roundDrawNum: number; - // 每满几论决斗一次 - public duelRoundNum: number; - // 第几次决斗后游戏结束 - public maxDuelNum: number; - // 玩家手牌数量上限 - public maxCardNum: number; - // 出牌公共时限 - public maxDiscardTime: number; - // 吃牌公共时限 - public maxEatTime: number; - // 操作公共时限 - public playerActTime: number; - // 玩家灵活时限 - public maxExtTime: number; - // 每回合增加玩家灵活时限数值 - public roundExtTime: number; - // 玩家随从上限 - public maxPlayerPetCount: number; - // 结算显示时间 - public resultShowTime: number; - // 基本奖励分 - public baseAddScore: number; - // 额外奖励分 - public extraAddScore: number; - // 游戏结果显示时间, 也是游戏重开等待时间 - public gameResultTime: number; - // 匹配等待时间, 时间结束后, 填充机器人; - public waitingPlayerTime: number; - // 匹配等待时, 每进入一个玩家, 等待时间延长n秒 - public waitingPlayerOnePlus: number; - // 英雄选择时间 - public pickHeroTime: number; - // 机器人操作最小时间 - public robotActTimeMin: number; - // 机器人操作最大时间 - public robotActTimeMax: number; - // 队友死亡后,补牌数量 - public teamDeadAddNum: number; - // 胡牌张数(自摸) - public selfEatCount: number; - // 胡牌张数(吃牌) - public otherEatCount: number; - // 轮空轮的间隔时间 - public emptyRoundTime: number; - // 玩家初始卡牌数 - public playerInitNums: number[] = []; - // 初级场能否吃牌 - public canEatBase: boolean; - // 进阶场能否吃牌 - public canEatAdv: boolean; - // 随从继承战力的比率 - public petInheritRate: number; + // 初始手牌数量 + public initCardNum: number + // 可更换的初始手牌上限 + public cardChangeNum: number + // 更换初始手牌时限 + public cardChangeTime: number + // 每回合发牌数量 + public roundDrawNum: number + // 每满几论决斗一次 + public duelRoundNum: number + // 第几次决斗后游戏结束 + public maxDuelNum: number + // 玩家手牌数量上限 + public maxCardNum: number + // 出牌公共时限 + public maxDiscardTime: number + // 吃牌公共时限 + public maxEatTime: number + // 操作公共时限 + public playerActTime: number + // 玩家灵活时限 + public maxExtTime: number + // 每回合增加玩家灵活时限数值 + public roundExtTime: number + // 玩家随从上限 + public maxPlayerPetCount: number + // 结算显示时间 + public resultShowTime: number + // 基本奖励分 + public baseAddScore: number + // 额外奖励分 + public extraAddScore: number + // 游戏结果显示时间, 也是游戏重开等待时间 + public gameResultTime: number + // 匹配等待时间, 时间结束后, 填充机器人; + public waitingPlayerTime: number + // 匹配等待时, 每进入一个玩家, 等待时间延长n秒 + public waitingPlayerOnePlus: number + // 英雄选择时间 + public pickHeroTime: number + // 机器人操作最小时间 + public robotActTimeMin: number + // 机器人操作最大时间 + public robotActTimeMax: number + // 队友死亡后,补牌数量 + public teamDeadAddNum: number + // 胡牌张数(自摸) + public selfEatCount: number + // 胡牌张数(吃牌) + public otherEatCount: number + // 轮空轮的间隔时间 + public emptyRoundTime: number + // 玩家初始卡牌数 + public playerInitNums: number[] = [] + // 初级场能否吃牌 + public canEatBase: boolean + // 进阶场能否吃牌 + public canEatAdv: boolean + // 随从继承战力的比率 + public petInheritRate: number + // 低级机器人的胜率值 + public robotLvlLow: number + // 高级机器人的胜率值 + public robotLvlHigh: number - public init(data: Map) { - this.initCardNum = data.get(BaseConst.INIT_CARD_NUM).value; - this.cardChangeNum = data.get(BaseConst.CARD_CHANGE_NUM).value; - this.cardChangeTime = data.get(BaseConst.CARD_CHANGE_TIME).value; - this.roundDrawNum = data.get(BaseConst.ROUND_DRAW_NUM).value; - this.duelRoundNum = data.get(BaseConst.DUEL_ROUND_NUM).value; - this.maxDuelNum = data.get(BaseConst.MAX_DUEL_NUM).value; - this.maxCardNum = data.get(BaseConst.MAX_CARD_NUM).value; - this.maxDiscardTime = data.get(BaseConst.MAX_DISCARD_TIME).value; - this.maxEatTime = data.get(BaseConst.MAX_EAT_TIME).value; - this.playerActTime = data.get(BaseConst.PLAYER_ACT_TIME).value; - this.maxExtTime = data.get(BaseConst.MAX_EXT_TIME).value; - this.roundExtTime = data.get(BaseConst.ROUND_EXT_TIME).value; - this.maxPlayerPetCount = data.get(BaseConst.MAX_PLAYER_PET_COUNT).value; - this.resultShowTime = data.get(BaseConst.ROUND_SHOW_TIME).value; - this.baseAddScore = data.get(BaseConst.BASE_ADD_SCORE).value; - this.extraAddScore = data.get(BaseConst.EXTRA_ADD_SCORE).value; - this.gameResultTime = data.get(BaseConst.GAME_RESULT_TIME).value; - this.waitingPlayerTime = data.get(BaseConst.WAITING_PLAYER_TIME).value; - this.waitingPlayerOnePlus = data.get(BaseConst.WAITING_PLAYER_ONEPLUS).value; - this.pickHeroTime = data.get(BaseConst.PICK_HERO_TIME).value; - this.robotActTimeMin = data.get(BaseConst.ROBOT_ACTTIME_MIN).value; - this.robotActTimeMax = data.get(BaseConst.ROBOT_ACTTIME_MAX).value; - this.teamDeadAddNum = data.get(BaseConst.TEAM_DEAD_ADDNUM).value; - this.selfEatCount = data.get(BaseConst.SELF_EAT_COUNT).value; - this.otherEatCount = data.get(BaseConst.OTHER_EAT_COUNT).value; - this.emptyRoundTime = data.get(BaseConst.EMPTY_ROUND_TIME).value; - this.playerInitNums = [ - data.get(BaseConst.PLAYER1_INIT_NUM).value, - data.get(BaseConst.PLAYER2_INIT_NUM).value, - data.get(BaseConst.PLAYER3_INIT_NUM).value, - data.get(BaseConst.PLAYER4_INIT_NUM).value, - ] - this.canEatBase = !!data.get(BaseConst.CAN_EAT_BASE).value; - this.canEatAdv = !!data.get(BaseConst.CAN_EAT_ADV).value; - this.petInheritRate = data.get(BaseConst.PET_INHERIT_RATE).value / 100; - } + public init(data: Map) { + this.initCardNum = data.get(BaseConst.INIT_CARD_NUM).value + this.cardChangeNum = data.get(BaseConst.CARD_CHANGE_NUM).value + this.cardChangeTime = data.get(BaseConst.CARD_CHANGE_TIME).value + this.roundDrawNum = data.get(BaseConst.ROUND_DRAW_NUM).value + this.duelRoundNum = data.get(BaseConst.DUEL_ROUND_NUM).value + this.maxDuelNum = data.get(BaseConst.MAX_DUEL_NUM).value + this.maxCardNum = data.get(BaseConst.MAX_CARD_NUM).value + this.maxDiscardTime = data.get(BaseConst.MAX_DISCARD_TIME).value + this.maxEatTime = data.get(BaseConst.MAX_EAT_TIME).value + this.playerActTime = data.get(BaseConst.PLAYER_ACT_TIME).value + this.maxExtTime = data.get(BaseConst.MAX_EXT_TIME).value + this.roundExtTime = data.get(BaseConst.ROUND_EXT_TIME).value + this.maxPlayerPetCount = data.get(BaseConst.MAX_PLAYER_PET_COUNT).value + this.resultShowTime = data.get(BaseConst.ROUND_SHOW_TIME).value + this.baseAddScore = data.get(BaseConst.BASE_ADD_SCORE).value + this.extraAddScore = data.get(BaseConst.EXTRA_ADD_SCORE).value + this.gameResultTime = data.get(BaseConst.GAME_RESULT_TIME).value + this.waitingPlayerTime = data.get(BaseConst.WAITING_PLAYER_TIME).value + this.waitingPlayerOnePlus = data.get(BaseConst.WAITING_PLAYER_ONEPLUS).value + this.pickHeroTime = data.get(BaseConst.PICK_HERO_TIME).value + this.robotActTimeMin = data.get(BaseConst.ROBOT_ACTTIME_MIN).value + this.robotActTimeMax = data.get(BaseConst.ROBOT_ACTTIME_MAX).value + this.teamDeadAddNum = data.get(BaseConst.TEAM_DEAD_ADDNUM).value + this.selfEatCount = data.get(BaseConst.SELF_EAT_COUNT).value + this.otherEatCount = data.get(BaseConst.OTHER_EAT_COUNT).value + this.emptyRoundTime = data.get(BaseConst.EMPTY_ROUND_TIME).value + this.playerInitNums = [ + data.get(BaseConst.PLAYER1_INIT_NUM).value, + data.get(BaseConst.PLAYER2_INIT_NUM).value, + data.get(BaseConst.PLAYER3_INIT_NUM).value, + data.get(BaseConst.PLAYER4_INIT_NUM).value + ] + this.canEatBase = !!data.get(BaseConst.CAN_EAT_BASE).value + this.canEatAdv = !!data.get(BaseConst.CAN_EAT_ADV).value + this.petInheritRate = data.get(BaseConst.PET_INHERIT_RATE).value / 100 + this.robotLvlLow = data.get(BaseConst.ROBOT_LVL_LOW).value + this.robotLvlHigh = data.get(BaseConst.ROBOT_LVL_HIGHT).value + } } diff --git a/src/constants/BaseConst.ts b/src/constants/BaseConst.ts index 274fb36..923b857 100644 --- a/src/constants/BaseConst.ts +++ b/src/constants/BaseConst.ts @@ -62,6 +62,10 @@ export class BaseConst { public static readonly CAN_EAT_ADV = 99040 // 随从继承比例 public static readonly PET_INHERIT_RATE = 99041 + // 低级机器人的胜率值 + public static readonly ROBOT_LVL_LOW = 99042 + // 高级机器人的胜率值 + public static readonly ROBOT_LVL_HIGHT = 99044 public static readonly COMPOUND = 'compound' public static readonly EFFECTCARD = 'effectcard' diff --git a/src/global.d.ts b/src/global.d.ts index b9d2e93..be797b9 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -306,6 +306,14 @@ declare module 'colyseus' { */ getOppositePlayer(srcPlayer: string | Player): Player; + /** + * 获取另外一队的玩家 + * @param {string | Player} srcPlayer + * @param exPlayer + * @return {Player[]} + */ + getOtherTeamPlayers(srcPlayer: string, exPlayer?: string ): Player[]; + /** * 根据index获取玩家 * @param {number} idx diff --git a/src/robot/Robot.ts b/src/robot/Robot.ts index 1f64129..c6b3d43 100644 --- a/src/robot/Robot.ts +++ b/src/robot/Robot.ts @@ -14,6 +14,7 @@ export class Robot { client: Client myTurn: boolean = false player: Player + cheatRate: number = 0 constructor(host: string, roomId: string) { this.host = host @@ -64,6 +65,10 @@ export class Robot { self.selectPet() } break + case 'update_change_rate': + log(`update cheat rate to: ${data.val}`) + self.cheatRate = data.val + break } }) @@ -170,7 +175,8 @@ export class Robot { } let self = this let cardArr = [...self.player.cards.values()] - let cards = assistantUtil.checkDiscard(cardArr, targetCard) + let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate}) + let cards = result.cards; if (!cards || cards.length == 0) { return } @@ -191,6 +197,9 @@ export class Robot { if (hasEatCard) { repData.target = targetCard.id } + if (result.nums) { + repData.nums = result.nums + } self.reply('discard_card_c2s', repData) } @@ -202,7 +211,8 @@ export class Robot { private async eatOrGiveUp() { let targetCard = [...this.room.state.cards.values()][0] let cardArr = [...this.player.cards.values()] - let tmpCards = assistantUtil.checkDiscard(cardArr, targetCard) + let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate}) + let tmpCards = result.cards; let next = this.giveup.bind(this) if (tmpCards.length > 1 && targetCard.type === 1) { let cardIds: number[] = [] diff --git a/src/robot/RobotClient.ts b/src/robot/RobotClient.ts index d2d7729..d67e857 100644 --- a/src/robot/RobotClient.ts +++ b/src/robot/RobotClient.ts @@ -31,6 +31,7 @@ export class RobotClient implements Client { listenerState: any listenerTurn: any active: boolean = false + cheatRate: number = 0 constructor(sessionId: string, state: CardGameState, onMessageHandlers: { [id: string]: (client: Client, message: any) => void }) { this.sessionId = sessionId @@ -86,6 +87,10 @@ export class RobotClient implements Client { self.selectPet() } break + case 'update_change_rate': + log(`update cheat rate to: ${data.val}`) + self.cheatRate = data.val + break } } @@ -147,7 +152,8 @@ export class RobotClient implements Client { } let self = this let cardArr = [...self.selfPlayer.cards.values()] - let cards = assistantUtil.checkDiscard(cardArr, targetCard) + let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate}) + let cards = result.cards if (!cards || cards.length == 0) { return } @@ -168,6 +174,9 @@ export class RobotClient implements Client { if (hasEatCard) { repData.target = targetCard.id } + if (result.nums) { + repData.nums = result.nums + } self.reply('discard_card_c2s', repData) } @@ -179,7 +188,8 @@ export class RobotClient implements Client { private async eatOrGiveUp() { let targetCard = [...this.svrstate.cards.values()][0] let cardArr = [...this.selfPlayer.cards.values()] - let tmpCards = assistantUtil.checkDiscard(cardArr, targetCard) + let result = assistantUtil.checkDiscard({cardArr, card: targetCard, rate: this.cheatRate}) + let tmpCards = result.cards let next = this.giveup.bind(this) if (tmpCards.length > 1 && targetCard.type === 1) { let cardIds: number[] = [] diff --git a/src/rooms/GeneralRoom.ts b/src/rooms/GeneralRoom.ts index a60fe42..8588157 100644 --- a/src/rooms/GeneralRoom.ts +++ b/src/rooms/GeneralRoom.ts @@ -86,7 +86,8 @@ export class GeneralRoom extends Room { client, cards: message.cards, target: message.target, - dtype: 0 + dtype: 0, + nums: message.nums }) }) this.onMessage('eat_card_c2s', (client, message) => { @@ -399,4 +400,16 @@ export class GeneralRoom extends Room { let opposIdx = ((this.maxClients / 2 | 0) + idx) % this.maxClients return this.getPlayerByIdx(opposIdx) } + getOtherTeamPlayers(srcPlayer: string, exPlayer?: string): Player[] { + let team = this.state.players.get(srcPlayer).team + let results:Player[] = [] + for (let [,player] of this.state.players) { + if (player.team !== team) { + if (exPlayer && player.id != exPlayer) { + results.push(player) + } + } + } + return results + } } diff --git a/src/rooms/commands/BeginGameCommand.ts b/src/rooms/commands/BeginGameCommand.ts index bc57772..8c3c704 100644 --- a/src/rooms/commands/BeginGameCommand.ts +++ b/src/rooms/commands/BeginGameCommand.ts @@ -4,6 +4,7 @@ import { GameStateConst } from '../../constants/GameStateConst' import gameUtil from '../../utils/game.util' import { GameEnv } from '../../cfg/GameEnv' import { NextTurnCommand } from './NextTurnCommand' +import { debugRoom } from '../../common/Debug' /** * 开始游戏 @@ -18,9 +19,49 @@ export class BeginGameCommand extends Command { let card1 = gameUtil.initCardQue(card0.length + 1, this.state.advMode) let cardAll = card0.concat(card1) cardAll.randomSort() - //FixMe:: 移除 - // let card0 = gameUtil.initSampleCards(1) - // this.state.cardQueue = card0; + // 如果是匹配模式, 挑战机器人作弊比率 + if (this.state.mode == 1) { + let highRate = new GameEnv().robotLvlHigh / 100 + let lowRate = new GameEnv().robotLvlLow / 100 + for (let [, player] of this.state.players) { + if (!player.robot) { + continue + } + let client = this.room.getClient(player) + let oplayer = this.room.getOppositePlayer(player) + if (oplayer.robot) { + let eplayers = this.room.getOtherTeamPlayers(player.id, oplayer.id) + if (!eplayers || eplayers.length == 0) { + continue + } + for (let p of eplayers) { + if (!p.robot) { + oplayer = p + break + } + } + if (oplayer.robot) { + continue + } + } + + let rate = 0 + if (oplayer.winRate > highRate) { + rate = oplayer.winRate * 100 | 0 + } else if (oplayer.winRate > lowRate) { + rate = oplayer.winRate / 2 * 100 | 0 + } + debugRoom(`opposite play win rate: ${oplayer.winRate}, robot change rate: ${rate}`) + if (global.isProd) { + client.send('update_change_rate', { val: rate }) + } else { + client.send('update_change_rate', { val: 100 }) + } + let assistClient = this.room.getAssistClient(player.id) + assistClient.send('update_change_rate', { val: rate }) + } + } + this.state.cardQueue = cardAll let i = 0 for (let [id] of this.state.players) { diff --git a/src/rooms/commands/DiscardCommand.ts b/src/rooms/commands/DiscardCommand.ts index 9e6a6b4..72ab266 100644 --- a/src/rooms/commands/DiscardCommand.ts +++ b/src/rooms/commands/DiscardCommand.ts @@ -12,6 +12,7 @@ import { StateTypeEnum } from '../enums/StateTypeEnum' import { RULE_CANEAT, RULE_SINGLEEAT } from '../../cfg/RoomOptions' import { ClockNameConst } from '../../constants/ClockNameConst' import { stopDrawCardClock } from '../../utils/clock.util' +import { CardType } from '../../cfg/enums/CardType' /** * 出牌 @@ -19,13 +20,13 @@ import { stopDrawCardClock } from '../../utils/clock.util' * type: 0, 正常的抽牌 * type: 1, 到时间后, 自动的抽牌 */ -export class DiscardCommand extends Command { +export class DiscardCommand extends Command { // validate({ client, cards } = this.payload) { // const player = this.state.players.get(client.sessionId); // return player !== undefined && gameUtil.checkCardsExists(player.cards, cards); // } - async execute({ client, cards, target, dtype } = this.payload) { + async execute({ client, cards, target, dtype , nums} = this.payload) { const player = this.state.players.get(client.sessionId) if (!player) { this.room.send(client, 'discard_card_s2c', { @@ -58,6 +59,17 @@ export class DiscardCommand extends Command { - async execute({client, accountId, seat, score} = this.payload) { - let count = this.state.players.size; + async execute({ client, accountId, seat, score } = this.payload) { + let count = this.state.players.size if (count >= this.room.maxClients) { - return; + return } // begin of set seat and team - let idx = count; - let seatSet = new Set([0,1,2,3]) + let idx = count + let seatSet = new Set([0, 1, 2, 3]) let accounts: string[] = [] - for (let [,p] of this.state.players) { + for (let [, p] of this.state.players) { seatSet.delete(p.idx) accounts.push(p.accountId) } if (seat != undefined) { seat = +seat if (seatSet.has(seat)) { - idx = seat; + idx = seat } else { idx = seatSet.values().next().value } @@ -42,70 +41,73 @@ export class OnJoinCommand extends Command parseInt(o+'')) + player.heros = uinfo.heros.map(o => parseInt(o + '')) + player.robot = false + player.winRate = uinfo.rate < 0 ? 0 : uinfo.rate } else { - const fc = global.$cfg.get(BaseConst.FORMULA); - let low = (this.room.score * fc.get(70034).number / 100) | 0; - let high = (this.room.score * fc.get(70035).number / 100) | 0; + const fc = global.$cfg.get(BaseConst.FORMULA) + let low = (this.room.score * fc.get(70034).number / 100) | 0 + let high = (this.room.score * fc.get(70035).number / 100) | 0 uinfo = await randomUserInfo(low, high, accounts) + player.robot = true } accountId = uinfo.accountid - player.accountId = accountId; + player.accountId = accountId player.nickname = uinfo.nickname player.avatar = uinfo.avatar player.score = uinfo.score - this.room.addAssistClient(client.sessionId); - let self = this; + this.room.addAssistClient(client.sessionId) + let self = this if (!this.room.match && !this.room.robotCount) { if (this.state.players.size >= this.room.maxClients) { this.room.lock().then(() => { - }); - this.state.updateGameState(GameStateConst.STATE_WAIT_PREPARE); + }) + this.state.updateGameState(GameStateConst.STATE_WAIT_PREPARE) } } else { if (this.room.clientCount() == 1) { // 正常的匹配逻辑进入的第一个玩家, 开启定时, 超过设定时间人没齐的话, 添加机器人 let timeOutWaitingPlayer = async function () { - let count = self.room.maxClients - self.room.clientCount(); + let count = self.room.maxClients - self.room.clientCount() if (count > 0) { for (let i = 0; i < count; i++) { - await self.room.addRobot(); + await self.room.addRobot() } } } - let time = new GameEnv().waitingPlayerTime * 1000; - self.room.beginSchedule(time, timeOutWaitingPlayer, ClockNameConst.WAITING_PLAYER); + let time = new GameEnv().waitingPlayerTime * 1000 + self.room.beginSchedule(time, timeOutWaitingPlayer, ClockNameConst.WAITING_PLAYER) } else if (this.room.clientCount() > 1 && this.room.clientCount() < this.room.maxClients) { - let moreTime = new GameEnv().waitingPlayerOnePlus * 1000; + let moreTime = new GameEnv().waitingPlayerOnePlus * 1000 self.room.addScheduleTime(moreTime, 'play_join', ClockNameConst.WAITING_PLAYER) } if (this.state.players.size >= this.room.maxClients) { - this.room.stopSchedule(ClockNameConst.WAITING_PLAYER); + this.room.stopSchedule(ClockNameConst.WAITING_PLAYER) this.room.lock().then(() => { - }); - this.state.updateGameState(GameStateConst.STATE_WAIT_PREPARE); + }) + this.state.updateGameState(GameStateConst.STATE_WAIT_PREPARE) } else if (this.state.players.size < this.room.maxClients && this.state.players.size >= this.room.maxClients - this.room.robotCount) { for (let i = 0; i < this.room.robotCount; i++) { - this.room.robotCount --; - await self.room.addRobot(); + this.room.robotCount-- + await self.room.addRobot() } } } - this.room.bUserJoin(`${client.sessionId}`, {except: client}); + this.room.bUserJoin(`${ client.sessionId }`, { except: client }) } } diff --git a/src/rooms/commands/SelectPetCommand.ts b/src/rooms/commands/SelectPetCommand.ts index 709b6e7..6cc6662 100644 --- a/src/rooms/commands/SelectPetCommand.ts +++ b/src/rooms/commands/SelectPetCommand.ts @@ -101,7 +101,7 @@ export class SelectPetCommand extends Command 1) { + if (multipEat && assistantUtil.checkDiscard({cardArr: [...player.cards.values()]}).cards.length > 1) { 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}`) diff --git a/src/rooms/schema/Player.ts b/src/rooms/schema/Player.ts index ae6bf0a..605036c 100644 --- a/src/rooms/schema/Player.ts +++ b/src/rooms/schema/Player.ts @@ -108,8 +108,11 @@ export class Player extends Schema { * 用于记录pet值, 用于统计伤害 */ petData: Map = new Map(); - heros: number[]; + // 是否是机器人 + robot: boolean; + // 十场胜率 + winRate: number; /** * 英雄绑定的卡组, 选好英雄后, 从默认配置或玩家卡组(待实现)中获取 diff --git a/src/utils/assistant.util.ts b/src/utils/assistant.util.ts index 7d3941a..6e0a3c8 100644 --- a/src/utils/assistant.util.ts +++ b/src/utils/assistant.util.ts @@ -12,6 +12,7 @@ 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, key: number, value: Card) { if (map.has(key)) { @@ -30,7 +31,7 @@ let assistantUtil = { * @param cardArr 待检查的卡组 * @param card 目标牌 */ - checkDiscard(cardArr: Card[], card?: Card): 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 = new Map() let cardIdSet: Set = new Set() @@ -65,7 +66,7 @@ let assistantUtil = { } if (fetched) { - return result + return {cards: result} } let cardIds = [...cardIdSet] @@ -115,9 +116,76 @@ let assistantUtil = { result.push(pointMap.get(point)[0]) } } - return result + return {cards: result} } else { - return [cardArr.randomOne()] + if (cardArr.length > maxCount && rate > 0) { + robotLog(`begin cheat ^_^`) + let random = getRandom(0, 100) + if (random <= rate) { + let max = Math.min(maxCount+1, 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()]} } }, /** diff --git a/src/utils/game.util.ts b/src/utils/game.util.ts index 405f028..f06e15f 100644 --- a/src/utils/game.util.ts +++ b/src/utils/game.util.ts @@ -52,6 +52,19 @@ let gameUtil = { debugRoom(cards) return cards }, + randomEffect(advMode: boolean): number { + let effCfgMap: Map = global.$cfg.get(BaseConst.EFFECTCARD) + let results = [] + for (let [,effCfg] of effCfgMap) { + if (effCfg.type_id !== 2) { + continue + } + if ((advMode && effCfg.intermediateaccess) || (!advMode && effCfg.primaryaccess)) { + results.push(effCfg.id) + } + } + return results.randomOne() + }, /** * 随机生成一张指定效果的卡 * @param effectId