From df5e30def4b5e4c5561be5b5193692874e985b32 Mon Sep 17 00:00:00 2001 From: LIUZHAO Date: Mon, 18 Mar 2024 16:36:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E5=90=8D=E6=8A=95=E7=A5=A8bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- client/src/pages/gaming/Gaming.jsx | 34 ++++++++++++------------- client/src/pages/gaming/Instruction.jsx | 2 +- client/src/pages/room/Room.jsx | 4 +-- server/handler/checkout.go | 27 ++++++++++++-------- server/handler/execute.go | 30 ++++++++-------------- server/handler/game.go | 3 +++ server/handler/toggleNight.go | 13 +++++++--- server/handler/vote.go | 4 +-- 9 files changed, 63 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 1ed9239..4b3fdff 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ + 邪恶 1. 圣徒被投票处决,且未中毒 2. 平民阵营被屠城 - 3. 活人数小于等于4,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长 + 3. 活人数小于等于4,未发生爪牙转化为恶魔,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长 + 与无辅助器的不同之处 + 没有说书人 + 全程不需闭眼 diff --git a/client/src/pages/gaming/Gaming.jsx b/client/src/pages/gaming/Gaming.jsx index f9a3ac3..b76f57f 100644 --- a/client/src/pages/gaming/Gaming.jsx +++ b/client/src/pages/gaming/Gaming.jsx @@ -40,7 +40,7 @@ function Gaming() { } socket.onmessage = function(event) { // TODO 内测用,记得关闭 - // console.log("Received message from server:", JSON.parse(event.data)) + console.log("Received message from server:", JSON.parse(event.data)) setGame(JSON.parse(event.data)) } socket.onerror = function(error) { @@ -212,14 +212,14 @@ function Gaming() { let me = getMe(game) // 当前玩家死亡,他不能提名,不能施法,则他看其他死了的玩家就是加灰色不能选择 // 当前玩家没死,他就不可能看到灰色 - if (me.state.dead) { - for (let i = 0; i < game.players.length; i++) { - if (game.players[i].state.dead) { - let seat = document.getElementById(game.players[i].id) - if (!seat.classList.contains("highlight-dead")) { - seat.classList.add("highlight-dead") - seat.classList.add("highlight-dead-cant-be-selected") - } + for (let i = 0; i < game.players.length; i++) { + if (game.players[i].state.dead) { + let seat = document.getElementById(game.players[i].id) + if (!seat.classList.contains("highlight-dead")) { + seat.classList.add("highlight-dead") + } + if (me.state.dead && !seat.classList.contains("highlight-dead-cant-be-selected")) { + seat.classList.add("highlight-dead-cant-be-selected") } } } @@ -234,9 +234,9 @@ function Gaming() { for (let i = 0; i < game.players.length; i++) { // 投票标签 tagTou = document.getElementById(game.players[i].id + "-tou") - if (game.players[i].ready.vote > 0 && tagTou.classList.contains("tag-hidden")) { + if (game.players[i].ready.vote && tagTou.classList.contains("tag-hidden")) { tagTou.classList.remove("tag-hidden") - } else if (game.players[i].ready.vote === 0 && !tagTou.classList.contains("tag-hidden")) { + } else if (!game.players[i].ready.vote && !tagTou.classList.contains("tag-hidden")) { tagTou.classList.add("tag-hidden") if (game.players[i].state.master) { butlerTou = true @@ -526,7 +526,7 @@ function Gaming() { let me = getMe(game) if (me.ready.vote && game.state.votingStep && game.state.stage !== 0) { for (let j = 0; j < game.players.length; j++) { - if (game.players[j].state.nominated) { + if (game.nominated) { emitVote() break } @@ -646,15 +646,15 @@ function Gaming() { return "本局未开始,不能投票" } if (!me.ready.vote) { - return "您本阶段已投过票" + return "您已不能投票" } if (!game.state.votingStep) { return "不在投票处决环节不能投票" } - if (me.ready.vote > 0 && game.state.votingStep) { + if (me.ready.vote && game.state.votingStep) { let content = "你确定要投票给玩家 " for (let j = 0; j < game.players.length; j++) { - if (game.players[j].state.nominated) { + if (game.nominated) { content += "<" + game.players[j].name + "> " break } @@ -673,7 +673,7 @@ function Gaming() { if (me.state.dead) { return "您已死亡" } - if (game.state.votingStep) { + if (game.state.votingStep && me.character !== "杀手") { return "投票阶段不能发动技能" } let selectedPlayersObj = [] @@ -956,7 +956,7 @@ function Gaming() { closable={false} onClose={onClose} open={open} - key="top" + key="instruction" > diff --git a/client/src/pages/gaming/Instruction.jsx b/client/src/pages/gaming/Instruction.jsx index a4abd32..3f17ce6 100644 --- a/client/src/pages/gaming/Instruction.jsx +++ b/client/src/pages/gaming/Instruction.jsx @@ -20,7 +20,7 @@ const text = ` + 邪恶 1. 圣徒被投票处决,且未中毒 2. 平民阵营被屠城 - 3. 活人数小于等于4,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长 + 3. 活人数小于等于4,未发生爪牙转化为恶魔,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长 + 与无辅助器的不同之处 + 没有说书人 + 全程不需闭眼 diff --git a/client/src/pages/room/Room.jsx b/client/src/pages/room/Room.jsx index e63aed7..3d56238 100644 --- a/client/src/pages/room/Room.jsx +++ b/client/src/pages/room/Room.jsx @@ -194,7 +194,7 @@ function Room() { closable={false} onClose={onCloseInstruction} open={openInstruction} - key="top" + key="instruction" > @@ -204,7 +204,7 @@ function Room() { closable={false} onClose={onCloseUpdateLog} open={openUpdateLog} - key="top" + key="updateLog" > diff --git a/server/handler/checkout.go b/server/handler/checkout.go index 1c74074..64a962f 100644 --- a/server/handler/checkout.go +++ b/server/handler/checkout.go @@ -170,23 +170,26 @@ func checkoutNight(mux *sync.Mutex, game *model.Room) { // 生成随机信息 for { randInt := rand.Intn(len(game.Players)) - if (game.Players[randInt].CharacterType == Outsiders || game.Players[randInt].State.Drunk) && - game.Players[randInt].Id != player.Id && game.Players[randInt].Character != Recluse && - game.Players[randInt].Character != Spy { + if game.Players[randInt].CharacterType == Outsiders && game.Players[randInt].Id != player.Id && + game.Players[randInt].Character != Recluse && game.Players[randInt].Character != Spy { outsider = game.Players[randInt] character = game.Players[randInt].Character break } + // 如果是酒鬼被选中 + if game.Players[randInt].State.Drunk && game.Players[randInt].Id != player.Id && + game.Players[randInt].Character != Recluse && game.Players[randInt].Character != Spy { + outsider = game.Players[randInt] + character = Drunk + break + } + // 如果间谍被选中 if game.Players[randInt].Character == Spy && game.Players[randInt].State.RegisteredAsType == Outsiders { outsider = game.Players[randInt] character = game.Players[randInt].State.RegardedAs break } } - // 如果是酒鬼被选中 - if outsider.CharacterType != Outsiders { - character = Drunk - } for { randInt := rand.Intn(len(game.Players)) if game.Players[randInt].Id != outsider.Id && game.Players[randInt].Id != player.Id { @@ -781,7 +784,7 @@ func checkoutNight(mux *sync.Mutex, game *model.Room) { msgAll = "" // 拼接日志 msgAll += fmt.Sprintf("[%s] ", fromPlayer.Name) - info := fmt.Sprintf("认定 [%s] 为主人,他投你可选投,他不投你也不能投\n", game.Players[toPlayerIndexSlice[0]].Name) + info := fmt.Sprintf("认定 [%s] 为主人,他投你可选投,他不投你票无效\n", game.Players[toPlayerIndexSlice[0]].Name) msgPlayer += info msgAll += info game.Players[fromPlayer.Index].Log += msgPlayer @@ -840,6 +843,7 @@ func checkout(game *model.Room, executed *model.Player) { var mayorAlive bool // 市长是否存活 var scarletWomanAlive bool // 魅魔是否存活 var poisonerAlive bool // 下毒者是否存活 + var demonCount int // 恶魔数量(不论死活) for _, player := range game.Players { // 对应平民胜利条件1 if player.CharacterType == Demons && !player.State.Dead { @@ -870,6 +874,9 @@ func checkout(game *model.Room, executed *model.Player) { if !player.State.Dead && (player.CharacterType == Demons || player.CharacterType == Minions) { evilAliveCount++ } + if player.CharacterType == Demons { + demonCount++ + } } // 平民胜利条件1(恶魔受不了了自杀情况),这里有三种铲除恶魔的可能:1、杀手,2、处决,3、自刀。 // 处决在结算投票时判定,枪杀在枪手施法后判定,自刀在判定刀人时判定,所以realDemonCount不可能为0 @@ -899,8 +906,8 @@ func checkout(game *model.Room, executed *model.Player) { } // 邪恶胜利条件3 halfAlive := int(math.Ceil(float64(aliveCount / 2))) - if game.Result == "" && aliveCount <= 4 && canVote-evilAliveCount <= halfAlive && evilAliveCount >= halfAlive && !hasSlayerBullet && !mayorAlive { - msg += "达成邪恶胜利条件三:活人数小于等于4,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长\n" + if game.Result == "" && aliveCount <= 4 && demonCount == 1 && canVote-evilAliveCount <= halfAlive && evilAliveCount >= halfAlive && !hasSlayerBullet && !mayorAlive { + msg += "达成邪恶胜利条件三:活人数小于等于4,未发生爪牙转化为恶魔,平民可投的票数不大于活人的半数(向上取整),且存活的邪恶玩家数量不小于活人的半数(向上取整),且没有杀手或有杀手没有子弹,且没有市长或市长已死或酒鬼市长\n" msg += "本局结束,邪恶胜利\n" game.Result = "邪恶阵营胜利" } diff --git a/server/handler/execute.go b/server/handler/execute.go index cbb0f9f..9764d2d 100644 --- a/server/handler/execute.go +++ b/server/handler/execute.go @@ -22,13 +22,7 @@ func execute(game *model.Room) { game.Players[i].Log += msg } game.Log += msg - // 发送日志 - broadcast(game) - // 判断圣徒 - 邪恶胜利条件4 - if game.Executed != nil && game.Executed.Character == Saint && !game.Executed.State.Poisoned { - checkout(game, game.Executed) - } // 判断魅魔 - 有人被处决,处决的人是小恶魔,活人大于等于5个,有魅魔且没死 var aliveCount int // 活人数量 var scarletWomanIndex = -1 @@ -58,22 +52,17 @@ func execute(game *model.Room) { emit(game, scarletWoman.Id) } - // 处决结束,清空票池,这里只复位和提名投票有关的状态,技能影响状态在toggleNight复位 - game.VoteLogs = map[string]string{} - game.VotePool = map[string]int{} - game.Nominated = nil - game.Executed = nil - for i := range game.Players { - game.Players[i].State.VotedFromButler = false - game.Players[i].State.VotedFromMaster = false - } - // 发送votingStep + // 发送日志 broadcast(game) // 立即结算 checkout(game, game.Executed) } func findExecutee(game *model.Room) (*model.Player, int) { + // 被圣女弹死 + if game.Executed != nil { + return game.Executed, 0 + } // 无人被提名 if len(game.VotePool) == 0 { return nil, 0 @@ -84,18 +73,19 @@ func findExecutee(game *model.Room) (*model.Player, int) { aliveCount++ } } - var halfAliveCount = int(math.Ceil(float64(aliveCount / 2))) + var halfAliveCount = int(math.Ceil(float64(aliveCount) / 2)) var executeeId string var executeeVoteCount int var isHighestRepeated bool for nominatedId, voteCount := range game.VotePool { + if voteCount >= halfAliveCount && voteCount == executeeVoteCount { + isHighestRepeated = true + continue + } if voteCount >= halfAliveCount && voteCount > executeeVoteCount { executeeId = nominatedId executeeVoteCount = voteCount } - if voteCount >= halfAliveCount && voteCount == executeeVoteCount { - isHighestRepeated = true - } } if executeeId != "" && !isHighestRepeated { for i, player := range game.Players { diff --git a/server/handler/game.go b/server/handler/game.go index 7b2f5c7..c93434b 100644 --- a/server/handler/game.go +++ b/server/handler/game.go @@ -382,6 +382,9 @@ func initStatus(players []model.Player, replaceDrunk string) []model.Player { players[i].CharacterType = Townsfolk players[i].Character = replaceDrunk players[i].State.Drunk = true + if replaceDrunk == Slayer { + players[i].State.Bullet = true + } case FortuneTeller: for { randIdx := rand.Intn(len(players)) diff --git a/server/handler/toggleNight.go b/server/handler/toggleNight.go index f9b2a8b..cc0c5a1 100644 --- a/server/handler/toggleNight.go +++ b/server/handler/toggleNight.go @@ -46,8 +46,15 @@ func toggleNight(mux *sync.Mutex, game *model.Room) { } else { game.State.Day += 1 msg = fmt.Sprintf("第%d天,天亮了~\n", game.State.Day+1) - // 天亮 清空executed + // 天亮 清空executed,和其他与投票提名相关的状态 + game.VoteLogs = map[string]string{} + game.VotePool = map[string]int{} + game.Nominated = nil game.Executed = nil + for i := range game.Players { + game.Players[i].State.VotedFromButler = false + game.Players[i].State.VotedFromMaster = false + } } // 存入总日志 game.Log += msg @@ -59,11 +66,11 @@ func toggleNight(mux *sync.Mutex, game *model.Room) { game.State.Night = !game.State.Night for i := range game.Players { - // 活人调整状态 - 让所有活人重新可以投票,夜转日结算,没投票还有票 + // 活人调整状态 - 夜转日结算,没死可以再提名 if !game.Players[i].State.Dead { game.Players[i].Ready.Nominate = true - game.Players[i].Ready.Nominated = true } + game.Players[i].Ready.Nominated = true // 调整玩家施放技能的准备状态 game.Players[i].State.Casted = true game.CastPool = map[string][]string{} diff --git a/server/handler/vote.go b/server/handler/vote.go index de7bd7b..636a1d1 100644 --- a/server/handler/vote.go +++ b/server/handler/vote.go @@ -26,6 +26,8 @@ func vote(mux *sync.Mutex, game *model.Room, playerId string) { // 管家的投票在endVoting结算 if game.Players[i].Character != Butler { msgAll += fmt.Sprintf("投票 [%s] 成功\n", game.Nominated.Name) + // 总日志加入票池 + game.VoteLogs[game.Nominated.Id] += msgAll } if game.Players[i].Character == Butler { game.Nominated.State.VotedFromButler = true @@ -33,8 +35,6 @@ func vote(mux *sync.Mutex, game *model.Room, playerId string) { if game.Players[i].State.Master { game.Nominated.State.VotedFromMaster = true } - // 总日志加入票池 - game.VoteLogs[game.Nominated.Id] += msgAll // 发送个人日志 emit(game, playerId) break