Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions consts/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ const (

// Room properties.
const (
RoomPropsDotShuffle = "ds"
RoomPropsLaiZi = "lz"
RoomPropsSkill = "sk"
RoomPropsPassword = "pwd"
RoomPropsPlayerNum = "pn"
RoomPropsChat = "ct"
RoomPropsShowIP = "ip"
RoomPropsDotShuffle = "ds"
RoomPropsLaiZi = "lz"
RoomPropsSkill = "sk"
RoomPropsPassword = "pwd"
RoomPropsPlayerNum = "pn"
RoomPropsChat = "ct"
RoomPropsShowIP = "ip"
RoomPropsJokerAsTarget = "jt"
)

var MnemonicSorted = []int{15, 14, 2, 1, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3}
Expand Down
47 changes: 47 additions & 0 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ var roomPropsSetter = map[string]func(r *Room, v string){
consts.RoomPropsShowIP: func(r *Room, v string) {
r.EnableShowIP = v == "on"
},
consts.RoomPropsJokerAsTarget: func(r *Room, v string) {
r.EnableJokerAsTarget = v == "on"
},
}

func init() {
Expand Down Expand Up @@ -115,6 +118,7 @@ func CreateRoom(creator int64, t int) *Room {
room.MaxPlayers = 10
case consts.GameTypeLiar:
room.MaxPlayers = 4
room.EnableJokerAsTarget = true
}
roomPlayers.Set(room.ID, map[int64]bool{})
roomSpectators.Set(room.ID, map[int64]int{})
Expand Down Expand Up @@ -163,11 +167,54 @@ func getPlayer(playerId int64) *Player {
}

func SetRoomProps(room *Room, k, v string) {
// 根据房间类型限制可设置的属性
allowedProps := getAllowedPropsByGameType(room.Type)

// 检查属性是否允许设置
if !allowedProps[k] {
return // 不允许的属性直接返回,不执行设置
}

if setter, ok := roomPropsSetter[k]; ok {
setter(room, v)
}
}

// 根据游戏类型返回允许设置的属性列表
func getAllowedPropsByGameType(gameType int) map[string]bool {
switch gameType {
case consts.GameTypeLiar:
// 对于骗子酒馆,只允许设置指示牌规则和显示IP
return map[string]bool{
consts.RoomPropsJokerAsTarget: true,
consts.RoomPropsShowIP: true,
}
case consts.GameTypeUno, consts.GameTypeMahjong:
// 对于Uno和麻将,只允许设置显示IP
return map[string]bool{
consts.RoomPropsShowIP: true,
}
case consts.GameTypeTexas:
// 对于德州扑克,允许设置玩家数量和显示IP
return map[string]bool{
consts.RoomPropsPlayerNum: true,
consts.RoomPropsShowIP: true,
}
default:
// 其他游戏类型允许所有常规属性
return map[string]bool{
consts.RoomPropsLaiZi: true,
consts.RoomPropsDotShuffle: true,
consts.RoomPropsSkill: true,
consts.RoomPropsPassword: true,
consts.RoomPropsPlayerNum: true,
consts.RoomPropsChat: true,
consts.RoomPropsShowIP: true,
consts.RoomPropsJokerAsTarget: true,
}
}
}

func getRoomPlayers(roomId int64) map[int64]bool {
if v, ok := roomPlayers.Get(roomId); ok {
return v.(map[int64]bool)
Expand Down
1 change: 1 addition & 0 deletions database/liar.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Liar struct {
LastPlayerID int64 `json:"lastPlayerId"`
LastPokers model.Pokers `json:"lastPokers"`
Supervisors map[int64]bool `json:"supervisors"`
AllowJokers bool `json:"allowJokers"`
}

func (l *Liar) Clean() {
Expand Down
35 changes: 18 additions & 17 deletions database/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,23 +232,24 @@ type RoomGame interface {
type Room struct {
sync.Mutex

ID int64 `json:"id"`
Type int `json:"type"`
Game RoomGame `json:"gameId"`
State int `json:"state"`
Players int `json:"players"`
Banker int `json:"banker"`
Robots int `json:"robots"`
Creator int64 `json:"creator"`
ActiveTime time.Time `json:"activeTime"`
MaxPlayers int `json:"maxPlayers"`
Password string `json:"password"`
EnableChat bool `json:"enableChat"`
EnableLaiZi bool `json:"enableLaiZi"`
EnableSkill bool `json:"enableSkill"`
EnableLandlord bool `json:"enableLandlord"`
EnableDontShuffle bool `json:"enableDontShuffle"`
EnableShowIP bool `json:"enableShowIP"`
ID int64 `json:"id"`
Type int `json:"type"`
Game RoomGame `json:"gameId"`
State int `json:"state"`
Players int `json:"players"`
Banker int `json:"banker"`
Robots int `json:"robots"`
Creator int64 `json:"creator"`
ActiveTime time.Time `json:"activeTime"`
MaxPlayers int `json:"maxPlayers"`
Password string `json:"password"`
EnableChat bool `json:"enableChat"`
EnableLaiZi bool `json:"enableLaiZi"`
EnableSkill bool `json:"enableSkill"`
EnableLandlord bool `json:"enableLandlord"`
EnableDontShuffle bool `json:"enableDontShuffle"`
EnableShowIP bool `json:"enableShowIP"`
EnableJokerAsTarget bool `json:"enableJokerAsTarget"`
}

func (r *Room) Model() model.Room {
Expand Down
62 changes: 46 additions & 16 deletions state/game/liar.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,31 @@ func (g *Liar) handlePlay(player *database.Player, game *database.Liar) error {
continue
}

// 处理出牌逻辑
// 检查输入是否只包含有效的牌面字符(q,k,a,s,x)和空格
isValidPokerInput := true
for _, char := range ans {
charStr := string(char)
if charStr != " " && poker.GetKey(charStr) == 0 {
isValidPokerInput = false
break
}
}

if !isValidPokerInput {
// 如果输入包含非牌面字符,则作为聊天消息
database.BroadcastChat(player, fmt.Sprintf("%s 说: %s\n", player.Name, ans))
continue
}

// 解析有效的牌面字符
keys := make([]int, 0)
for _, char := range ans {
key := poker.GetKey(string(char))
if key != 0 {
keys = append(keys, key)
charStr := string(char)
if charStr != " " { // 忽略空格
key := poker.GetKey(charStr)
if key != 0 {
keys = append(keys, key)
}
}
}

Expand Down Expand Up @@ -262,11 +281,8 @@ func (g *Liar) pullTrigger(player *database.Player, game *database.Liar) bool {

func (g *Liar) resetRound(game *database.Liar) {
deck := initLiarDeck()
// 重新抽取指示牌
if len(deck) > 0 {
game.Target = &deck[0]
deck = deck[1:]
}
// 根据游戏设置重新抽取指示牌
game.Target = selectTargetBasedOnSetting(deck, game.AllowJokers)

// 重新给存活玩家发放手牌
game.Hands = make(map[int64]model.Pokers)
Expand Down Expand Up @@ -390,14 +406,12 @@ func InitLiarGame(room *database.Room) (*database.Liar, error) {
supervisors := make(map[int64]bool)
deck := initLiarDeck()

// 抽取一张牌作为指示牌
// 抽取一张牌作为指示牌,根据房间设置决定是否允许大小王
var target *model.Poker
if len(deck) > 0 {
// 随机抽一张作为指示牌,通常不抽大小王作为基础指示牌,但用户没说,我们就直接从牌堆抽第一张
target = &deck[0]
deck = deck[1:]
}

// 从房间设置中获取是否允许大小王作为指示牌
// 使用 EnableJokerAsTarget 字段作为指示牌规则设置:启用时从牌堆随机抽取大小王,禁用时从Q/K/A三张牌中随机选取
allowJokers := room.EnableJokerAsTarget
target = selectTargetBasedOnSetting(deck, allowJokers)
for i, id := range playerIDs {
bullets[id] = rand.Intn(6) + 1
bong[id] = 0
Expand All @@ -421,6 +435,7 @@ func InitLiarGame(room *database.Room) (*database.Liar, error) {
Target: target,
Alive: alive,
Supervisors: supervisors,
AllowJokers: room.EnableJokerAsTarget, // 保存房间设置以供后续轮次使用
}, nil
}

Expand All @@ -435,3 +450,18 @@ func initLiarDeck() model.Pokers {
pokers.Shuffle(len(pokers), 1)
return pokers
}

// 根据设置抽取指示牌,如果允许大小王则从整个牌堆中抽取,否则从QKA中随机选择
func selectTargetBasedOnSetting(deck model.Pokers, allowJokers bool) *model.Poker {
if allowJokers && len(deck) > 0 {
// 如果允许大小王,则从整个牌堆中抽取第一张牌
return &deck[0]
} else {
// 如果不允许大小王,则从QKA中随机选择一张作为指示牌
// Q=12, K=13, A=1
targetKeys := []int{1, 12, 13}
selectedKey := targetKeys[rand.Intn(len(targetKeys))]
poker := poker.GetPokers(selectedKey)
return &poker[0]
}
}
10 changes: 7 additions & 3 deletions state/waiting.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,14 @@ func viewRoomPlayers(room *database.Room, currPlayer *database.Player) {
case consts.GameTypeTexas:
buf.WriteString(fmt.Sprintf("%-5s%-5v\n", "pn:", room.MaxPlayers))
buf.WriteString(fmt.Sprintf("%-5s%-5v\n", "ip:", sprintPropsState(room.EnableShowIP)))
case consts.GameTypeLiar:
buf.WriteString(fmt.Sprintf("%-5s%-5v\n", "jt:", sprintPropsState(room.EnableJokerAsTarget)))
buf.WriteString(fmt.Sprintf("%-5s%-5v\n", "ip:", sprintPropsState(room.EnableShowIP)))
default:
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "lz:", sprintPropsState(room.EnableLaiZi)+",", "ds:", sprintPropsState(room.EnableDontShuffle)))
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "sk:", sprintPropsState(room.EnableSkill)+",", "pn:", room.MaxPlayers))
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "ct:", sprintPropsState(room.EnableChat)+",", "ip:", sprintPropsState(room.EnableShowIP)))
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "lz:", sprintPropsState(room.EnableLaiZi)))
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "ds:", sprintPropsState(room.EnableDontShuffle)+",", "sk:", sprintPropsState(room.EnableSkill)))
buf.WriteString(fmt.Sprintf("%-5s%-5v%-5s%-5v\n", "pn:", room.MaxPlayers, "ct:", sprintPropsState(room.EnableChat)))
buf.WriteString(fmt.Sprintf("%-5s%-5v\n", "ip:", sprintPropsState(room.EnableShowIP)))
pwd := room.Password
if pwd != "" {
if room.Creator != currPlayer.ID {
Expand Down