using GameData; using MrWu.Debug; using PdkFriendServer.GlobalManager; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using GameMessage.PaoDeKuaiF; using GameFix.PaoDeKuaiF; using GameMessage; using Server.Data; namespace PdkFriendServer.Logic { /// /// 跑得快朋友房主逻辑 /// public partial class PdkGameMain { /// /// 游戏主包 /// public PdkGamePack GamePack; /// /// 服务器本地内存 /// public LogicMemory logicMemory; /// /// 规则 /// public PdkRule Rule; /// /// 桌子对象 /// public PdkGameDo DeskGameDo = null; public PdkGameMain(PdkGameDo _gamedo) { this.DeskGameDo = _gamedo; this.GamePack = new PdkGamePack(); } /// /// 游戏开始 /// public void GameStart() { byte shangyou = 0; //上游位置,从1开始 byte overJu = (byte)(this.DeskGameDo == null ? 0 : DeskGameDo.GetDeskInt(8)); //打完了几局,0就是一局都没有打完,也就是首局 shangyou = GamePack.Info.OverPos; var tg = GamePack.Info.PlayTuoGauan; GamePack = new PdkGamePack(); if (this.DeskGameDo != null) { SetFriendGz(); GamePack.Init(GamePack.Info.PlayNum); } else { //测试的规则 GamePack.Init(3); GamePack.Info.PlayNum = 3; //设置玩法规则 Rule = new PdkRule(); Rule.GuanPai = true; //经典玩法 Rule.BiYa = true;//不必压 Rule.ShouJu3 = true; Rule.SiDai3 = true; Rule.BaoZhuang = true; Rule.ZhaDanDeFen = true; } LoadInit(); if (overJu == 0) { logicMemory.BombCount = 0; } logicMemory.WarCount = overJu; logicMemory.ShangYou = shangyou; if (overJu != 0) { GamePack.Info.PlayTuoGauan = tg; } GamePack.Info.GameZT = 2; Log(Rule.ToString()); //this.GameFaPai(); //屏蔽掉,让dotime驱动流程玩下周 } /// /// 设置规则自动准备时间 /// void SetAutoReadTime() { if (this.Rule.TuoGuanNum <= 0) return; if (this.DeskGameDo == null) return; if (this.DeskGameDo.desk == null) return; if (this.DeskGameDo.desk.deskinfo == null) return; if (this.DeskGameDo.desk.deskinfo.rule == null) return; if (this.DeskGameDo.desk.deskinfo.rule.RuleEx == null) return; // if (!this.DeskGameDo.desk.deskinfo.rule.RuleEx.DepositAutoDissolve) return; if (this.DeskGameDo.desk.deskinfo.rule.RuleEx.AutoDeposit > 0) return; this.DeskGameDo.desk.deskinfo.rule.RuleEx.AutoDeposit = this.Rule.TuoGuanNum * 60; } /// /// 计时器 1秒钟执行一次 /// public void DoTime() { SetAutoReadTime(); switch (GamePack.Info.GameZT) { //case 1: // GameStart(); // break; case 2: GameFaPai(); break; case 3: BaoZhuangTuoGuan(); break; case 4: //if (Rule.TuoGuanNum > 0) //{//需要托管 DaPaiTuoGuan(); //} //玩家先手,并且是最后一张牌,就自动帮玩家出牌 if (GamePack.Info.MaxPlayCard.GameNum <= 0) { var cards = GamePack.CardPack.Cards[GamePack.Info.WhoPlay - 1].CardInfos.Where(x => x.GameState == 1).ToArray(); var b = PdkCardAlgorithm.GetOutCard(cards, cards, Rule, out var payCard); var zhad = PdkCardAlgorithm.IsHaveBomb(cards, Rule.AAAIsZhaDan); if (b && payCard.Ids.Length == cards.Length && payCard.Type != CardType1.SiDai2 && payCard.Type != CardType1.SiDai3 && !zhad) { payCard.Pos = (byte)GamePack.Info.WhoPlay; GamePack.Info.ActivePlayCard = payCard; Log($"最后一张牌,就自动帮玩家出牌 who:{GamePack.Info.WhoPlay}先出 ,托管出的牌:{payCard}"); GamePack.Info.ActivePlayCard = payCard; Debug.Info("最后一手GameDo"); GameDo(); } } break; case 5: if (this.TimeNum >= 2) { GameOver(); } break; default: // Log("DoTime default !"); break; } TimeNum++; } /// /// 游戏发牌 /// public void GameFaPai() { byte bc = 0; //计算这局的炸弹个数 for (int i = 0; i < 20; i++) { if (i > 0) { Log($"发牌i:{i} bnum:{bc} lc:{logicMemory.BombCount}", DebugLevel.ImportantLog); } InitCard(); bc = 0; bool b = false; for (int j = 0; j < GamePack.Info.PlayNum; j++) { byte bnum = CalcPlayBombRule(j); Log($"玩家:{j},bombCount:{bnum}"); //if (bnum > 1) //单个人一手牌不能有超过2个炸弹 //{ // bc += (byte)bnum; // break; //} if (bnum > 0) { bc += bnum; } } if (logicMemory.BombCount + bc <= 1) { logicMemory.BombCount += bc; b = true; } if (b) { break; } } CheckFeiJi(); if (Rule.HongTao10ZhaNiao) { //红桃十扎鸟 GamePack.Info.HongTaoShiPos = GetHongTaoShiPos(); } if (Rule.MeiJu3) { //每局黑桃3出 GamePack.Info.FistPlay = GetHeiTao3Pos(); Log($"第一个出牌位置:{GamePack.Info.FistPlay}"); } else if (Rule.ShouJu3) { //首局黑桃三先出,下局赢家出 GamePack.Info.FistPlay = logicMemory.WarCount == 0 ? GetHeiTao3Pos() : logicMemory.ShangYou; Log($"第一个出牌位置:{GamePack.Info.FistPlay},开始次数:{logicMemory.WarCount},上游玩家:{logicMemory.ShangYou}"); } GamePack.Info.WhoPlay = GamePack.Info.FistPlay; GamePack.Info.GameZT = (byte)(Rule.BaoZhuang ? 3 : 4); TimeNum = 0; SendPack(); } /// /// 包庄流程 /// public void GameBaoZhuang() { int bcount = 0;//包庄的人数 byte[] pos = new byte[GamePack.Info.PlayNum]; //包庄人的位置 bool zhuangB = false; if (GamePack.Info.BaoZhuang[GamePack.Info.FistPlay - 1] == 1) { //庄家包庄了,直接进入下一流程 GamePack.Info.WhoPlay = GamePack.Info.FistPlay; GamePack.Info.BaoPos = GamePack.Info.WhoPlay; GamePack.Info.GameZT = 4; //进入打牌 SetFalseOperation(); SendPack(); return; } else { for (byte i = 0; i < GamePack.Info.PlayNum; i++) { if (GamePack.Info.BaoZhuang[i] == 0) { // GamePack.Info.WhoPlay = GetNextPos(GamePack.Info.WhoPlay); SendPack(); return; //还有玩家没有操作,不处理流程 } if (GamePack.Info.BaoZhuang[i] == 1) { pos[bcount] = (byte)(i + 1); if (!zhuangB && pos[bcount] == GamePack.Info.FistPlay) { zhuangB = true; } bcount++; } } } if (bcount == 1) { GamePack.Info.WhoPlay = pos[0]; GamePack.Info.BaoPos = GamePack.Info.WhoPlay; } else if (bcount > 1) { //多个人包庄 if (zhuangB) {//如果庄家包庄了,那么就是庄家为包庄 GamePack.Info.WhoPlay = GamePack.Info.FistPlay; } else { //如果没有包庄的话,那么靠近庄家的下一家为包庄玩家 byte npos = GetNextPos(GamePack.Info.FistPlay); //庄的下家 for (int j = 0; j < pos.Length; j++) { bool b = false; for (byte i = 0; i < pos.Length; i++) { if (pos[i] == npos) { GamePack.Info.WhoPlay = pos[i]; b = true; break; } } if (!b) { npos = GetNextPos(npos); } else { break; } } } GamePack.Info.BaoPos = GamePack.Info.WhoPlay; } Log($"进入打牌,play:{GamePack.Info.WhoPlay} ,包庄玩家的位置:{GamePack.Info.BaoPos}"); GamePack.Info.GameZT = 4; //进入打牌 SetFalseOperation(); SendPack(); } /// /// 打牌流程 /// void GameDaPai() { Log("进入打牌流程,玩家出牌内容是:" + GamePack.Info.ActivePlayCard.ToString()); //如果玩家有出牌:1修改牌内存,2修改最大出牌信息 //记录炸弹计分 //判断一轮打完 //判断一局游戏打完 //转换控制权 一个玩家出完牌后 byte chupaiPos = 0; if (GamePack.Info.ActivePlayCard.Type != CardType1.None) { chupaiPos = GamePack.Info.ActivePlayCard.Pos; SetCardToOut(GamePack.Info.ActivePlayCard.Pos, GamePack.Info.ActivePlayCard.Ids); if (Rule.ZhaDanDeFen && GamePack.Info.ActivePlayCard.Type == CardType1.ZhaDan) { //炸弹得分,并且出的是炸弹 /*炸弹+10:打出炸弹+10分,不勾选0分 在有大必压得玩法下,一轮中打出的炸弹只算当局最大的炸弹分, 不必压得玩法下,只要打出炸弹都算分*/ AddZhaDanCount(GamePack.Info.ActivePlayCard.Pos, 1); // GamePack.Info.ZhaDans[GamePack.Info.ActivePlayCard.Pos - 1]++; if (Rule.BiYa && GamePack.Info.MaxPlayCard.Type == CardType1.ZhaDan) { //把之前加的炸弹减回去。 //GamePack.Info.ZhaDans[GamePack.Info.MaxPlayCard.Pos - 1]--; AddZhaDanCount(GamePack.Info.MaxPlayCard.Pos, -1); } } GamePack.Info.MaxPlayCard = GamePack.Info.ActivePlayCard; } if (IsGameOver(chupaiPos)) { //游戏是否结束 SendPack(); this.TimeNum = 0; GamePack.Info.GameZT = 5; // GameOver(); 修改为定时器驱动 return; } GamePack.Info.WhoPlay = GetNextPos(GamePack.Info.WhoPlay); Debug.Info($"当前玩家:{GamePack.Info.WhoPlay},下一个出牌的人:{GamePack.Info.WhoPlay}"); if (GamePack.Info.WhoPlay == GamePack.Info.MaxPlayCard.Pos) { //一轮结束 Log("一轮结束"); GamePack.Info.MaxPlayCard.Pos = 0; GamePack.Info.MaxPlayCard.GameNum = 0; GamePack.Info.MaxPlayCard.Type = CardType1.None; GamePack.Info.MaxPlayCard.Ids = null; } SendPack(); } void GameOver() { Log($"进入结算 bao:{GamePack.Info.BaoPos},overpos:{GamePack.Info.OverPos}"); int count = 0; if (Rule.JingDianWanFa || Rule.GuanPai) { count = 16; } if (Rule.Zhang15) { count = 15; } if (GamePack.Info.BaoPos > 0) { //有人包庄 var baoWin = GamePack.Info.BaoPos == GamePack.Info.OverPos; Log($"baowin:{baoWin}"); for (int i = 0; i < GamePack.Info.PlayNum; i++) { if (i + 1 != GamePack.Info.BaoPos) { //先统计闲家 int bei = GamePack.Info.HongTaoShiPos == i + 1 || GamePack.Info.HongTaoShiPos == GamePack.Info.BaoPos ? 4 : 2; //红桃十扎鸟 GamePack.Info.Score[i] += (baoWin ? 0 - count * bei : count * bei); } } } else { for (int i = 0; i < GamePack.Info.PlayNum; i++) {//先统计闲家 if (i + 1 != GamePack.Info.OverPos) { if (GamePack.Info.ShenYuCard[i] == 1) continue; var bei = GamePack.Info.HongTaoShiPos == i + 1 || GamePack.Info.HongTaoShiPos == GamePack.Info.OverPos ? 2 : 1;//红桃十扎鸟 var num = GamePack.Info.ShenYuCard[i] == count ? count * 2 : GamePack.Info.ShenYuCard[i]; GamePack.Info.Score[i] += 0 - num * bei; } } } for (int i = 0; i < GamePack.Info.PlayNum; i++) { if (i + 1 == (GamePack.Info.BaoPos > 0 ? GamePack.Info.BaoPos : GamePack.Info.OverPos)) { //统计庄家,把闲家的都加起来就是庄家的输赢 for (int j = 0; j < GamePack.Info.PlayNum; j++) { if (j == i) continue; GamePack.Info.Score[i] -= GamePack.Info.Score[j]; } } } for (int i = 0; i < GamePack.Info.PlayNum; i++) { if (GamePack.Info.ZhaDans[i] != 0) { GamePack.Info.Score[i] += (GamePack.Info.ZhaDans[i] * 10); } } //处理托管罚分 var fafen = GetTuoGuanFaFen(); if (fafen > 0) { var tgPos = GetTuoGuanPlay(); if (tgPos >= 0) { //有玩家托管 //int fen = fafen / (GamePack.Info.PlayNum - 1); for (int i = 0; i < GamePack.Info.PlayNum; i++) { if (i == tgPos) { GamePack.Info.Score[i] -= (fafen * (GamePack.Info.PlayNum - 1)); } else { GamePack.Info.Score[i] += fafen; } } } } #if DEBUG for (int i = 0; i < GamePack.Info.PlayNum; i++) { Log($"玩家:{(i + 1)} ,输赢:{GamePack.Info.Score[i]}"); } #endif if (DeskGameDo != null) { DeskGameDo.GameOver(); } } /// /// 是否托管罚分 /// /// 0不罚分 int GetTuoGuanFaFen() { if (this.DeskGameDo == null || this.DeskGameDo.desk == null || this.DeskGameDo.desk.deskinfo == null || this.DeskGameDo.desk.deskinfo.rule == null || this.DeskGameDo.desk.deskinfo.rule.RuleEx == null) return 0; return this.DeskGameDo.desk.deskinfo.rule.RuleEx.DepositAutoDissolve ? this.DeskGameDo.desk.deskinfo.rule.RuleEx.OutLinePenaltyPoint : 0; } /// /// 找打托管的玩家 /// /// 从0开始 -1未找到 int GetTuoGuanPlay() { return DeskGameDo.GetPlayerFirstDepositSeat(); //var desk = DeskGameDo.GetDesk(); //for (int i = 0; i < GamePack.Info.PlayNum; i++) //{ // if (desk[i] != null && desk[i].isDePosit) // {//找到在 托管的玩家 // return i; // } //} //return -1; } /// /// 游戏发包,发全包 /// void SendPack() { Log($"whoPlay:{GamePack.Info.WhoPlay}"); if (DeskGameDo == null) { var str = JsonPack.GetJson(this.GamePack); var dir = "./gamepack"; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); File.WriteAllText(Path.Combine(dir, "gamepack.txt"), str); var path = Path.Combine(dir, $"gamepack{DateTime.Now:yyyy-MM-dd-HH-mm-ss-fff}.txt"); Log("保存文件:" + path); File.WriteAllText(path, str); WaitWanJiaShuRu(); //等玩家输入。模拟玩家打牌 } else { SetOperation(); DeskGameDo.SendGamePack(); } } void SetFalseOperation() { for (int i = 0; i < GamePack.Info.PlayNum; i++) { this.SetWaitOperation(i, false); } } public void SetOperation() { for (int i = 0; i < GamePack.Info.PlayNum; i++) { var pl = this.DeskGameDo.desk[i]; if (pl != null) { GamePack.Info.PlayTuoGauan[i] = (byte)(pl.isDePosit ? 1 : 0); } bool b = false; //包庄流程是同时进行的 if (GamePack.Info.GameZT == 3) { b = GamePack.Info.BaoZhuang[i] == 0; } this.SetWaitOperation(i, GamePack.Info.GameZT == 3 ? b : i + 1 == GamePack.Info.WhoPlay); } } /// /// 设置玩家的操作权 /// /// 下标从0开始 /// public void SetWaitOperation(int seat, bool waitOperation) { var desk = this.DeskGameDo.GetDesk(); if (seat < 0 || seat >= desk.PlayerCnt) { return; } var pl = desk[seat]; if (pl != null) { //之前不能操作,现在可以操作,重置托管时间 if (!pl.WaitOperation && waitOperation) { pl.AutoDepositTime = 0; } pl.WaitOperation = waitOperation; } } /// /// 检查包内容是否合法 /// /// /// public bool CheckPack(PdkLogicInfo pack) { if (pack.WhoPlay != GamePack.Info.WhoPlay && GamePack.Info.GameZT > 3) return false; switch (GamePack.Info.GameZT) { case 3: //包庄 只能输入1和2 return pack.BaoZhuang[pack.WhoPlay - 1] == 1 || pack.BaoZhuang[pack.WhoPlay - 1] == 2; case 4: if (pack.WhoPlay != pack.ActivePlayCard.Pos) { Debug.Error($"who:{pack.WhoPlay},apos:{pack.ActivePlayCard}"); return false; } return CheckChuPai(pack.ActivePlayCard); } return true; } public void GameDo() { switch (GamePack.Info.GameZT) { //case 1: // GameStart(); // break; case 2: GameFaPai(); break; case 3: GameBaoZhuang(); break; case 4: GameDaPai(); break; case 5: GameOver(); break; default: Log("default GameDo game over!"); break; } } /// /// 等待玩家输入 /// void WaitWanJiaShuRu() { if (DeskGameDo != null) return; //正式连客户端以后要屏蔽这些代码。return string str = ""; byte num = 0; switch (GamePack.Info.GameZT) { case 3://包庄流程,只能输入1和2 Log("包庄操作 pos:" + GamePack.Info.WhoPlay); while (true) { str = Console.ReadLine(); if (string.IsNullOrWhiteSpace(str)) continue; Log(str); var ss = str.Split(','); if (ss.Length < 2) continue; byte.TryParse(ss[0], out var pos); byte.TryParse(ss[1], out num); GamePack.Info.WhoPlay = pos; GamePack.Info.BaoZhuang[pos - 1] = num; if (CheckPack(GamePack.Info)) { break; //如果包输入正确就跳走 } else { Log("检测不合格,输入非法值"); } } break; case 4: //打牌流程 Log("打牌操作 pos:" + GamePack.Info.WhoPlay); while (true) { str = Console.ReadLine(); //逗号分隔 if (string.IsNullOrWhiteSpace(str)) continue; var ss = str.Split(','); if (ss.Length <= 0) continue; Log(str); var selectCards = GamePack.CardPack.Cards[GamePack.Info.WhoPlay - 1].CardInfos.Where(x => ss.Any(s => s == x.ID.ToString())).ToArray(); PlayOutCardPdkF payCard; if (selectCards == null || selectCards.Length <= 0) //不要 { payCard = new PlayOutCardPdkF(); payCard.Pos = GamePack.Info.WhoPlay; payCard.Type = CardType1.None; GamePack.Info.ActivePlayCard = payCard; if (CheckPack(GamePack.Info)) { break; //如果包输入正确就跳走 } else { Log("检测不合格,输入非法值"); } } else if (PdkCardAlgorithm.GetOutCard(selectCards, GamePack.CardPack.Cards[GamePack.Info.WhoPlay - 1].CardInfos.Where(x => x.GameState == 1).ToArray(), this.Rule, out payCard)) { payCard.Pos = GamePack.Info.WhoPlay; GamePack.Info.ActivePlayCard = payCard; if (CheckPack(GamePack.Info)) { break; //如果包输入正确就跳走 } else { Log("检测不合格,输入非法值"); } } else { Log("输入的牌不符合规则,不能出下去"); } } break; case 6: //GameOver(); break; } } void textxxxx() { // GameStart(); // GameFaPai(); //PlayOutCard output = new PlayOutCard(); //output.Pos = 1; output.Type = CardType.LianDui; //output.GameNum = 9; //output.Ids = new byte[6]; //TCardInfo[] shoupai = new TCardInfo[16]; //shoupai[0] = new TCardInfo() { ID = 1, GameNum = 14, Flower = 1, Num = 14, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[1] = new TCardInfo() { ID = 27, GameNum = 14, Flower = 3, Num = 14, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[2] = new TCardInfo() { ID = 26, GameNum = 13, Flower = 2, Num = 13, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[3] = new TCardInfo() { ID = 25, GameNum = 12, Flower = 2, Num = 12, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[4] = new TCardInfo() { ID = 38, GameNum = 12, Flower = 3, Num = 12, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[5] = new TCardInfo() { ID = 36, GameNum = 10, Flower = 3, Num = 10, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[6] = new TCardInfo() { ID = 49, GameNum = 10, Flower = 4, Num = 10, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[7] = new TCardInfo() { ID = 35, GameNum = 9, Flower = 3, Num = 9, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[8] = new TCardInfo() { ID = 48, GameNum = 9, Flower = 4, Num = 9, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[9] = new TCardInfo() { ID = 8, GameNum = 8, Flower = 1, Num = 8, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[10] = new TCardInfo() { ID = 34, GameNum = 8, Flower = 3, Num = 8, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[11] = new TCardInfo() { ID = 5, GameNum = 5, Flower = 1, Num = 5, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[12] = new TCardInfo() { ID = 18, GameNum = 5, Flower = 2, Num = 5, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[13] = new TCardInfo() { ID = 44, GameNum = 5, Flower = 4, Num = 5, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[14] = new TCardInfo() { ID = 16, GameNum = 3, Flower =2, Num = 3, Score = 0, GameOwer = 1, GameState = 1 }; //shoupai[15] = new TCardInfo() { ID = 29, GameNum = 3, Flower = 3, Num = 3, Score = 0, GameOwer = 1, GameState = 1 }; //var tishi = PdkCardAlgorithm.GetTipCard(output, shoupai, null); //Console.WriteLine(tishi); } /// /// 测试函数 /// public void Test(string path = "") { //textxxxx(); //return; if (File.Exists("output.txt")) { File.Delete("output.txt"); } string testDir = !string.IsNullOrWhiteSpace(path) ? path : "./test"; if (!Directory.Exists(testDir)) { Directory.CreateDirectory(testDir); } foreach (string file in Directory.GetFiles(testDir)) { File.Delete(file); } bool b = true; GamePack.Info.GameZT = 1; if (!string.IsNullOrWhiteSpace(path)) { GamePack = JsonPack.GetData(File.ReadAllText(path)); } while (b) { switch (GamePack.Info.GameZT) { case 1: GameStart(); break; case 2: GameFaPai(); break; case 3: GameBaoZhuang(); break; case 4: GameDaPai(); break; case 5: GameOver(); GamePack.Info.GameZT = 11; //进入结束就结束 break; default: b = false; Log("test over!"); break; } } } void WriteToConsoleAndFile(StreamWriter writer, string message) { Console.WriteLine(message); // 写入控制台 writer.WriteLine(message); // 写入文件 } public void Log(string msg, DebugLevel leve = DebugLevel.Info) { if (DeskGameDo == null) { using (StreamWriter writer = new StreamWriter("output.txt", true)) // 第二个参数为true表示追加到文件 { WriteToConsoleAndFile(writer, $"[{DateTime.Now.ToString("G")}]:" + msg); } Thread.Sleep(1); } else { switch (leve) { case DebugLevel.Info: Debug.Info(msg); break; case DebugLevel.Warning: Debug.Warning(msg); break; case DebugLevel.ImportantLog: Debug.ImportantLog(msg); break; case DebugLevel.Error: Debug.Error(msg); break; case DebugLevel.Fatal: Debug.Fatal(msg); break; default: Debug.Info(msg); break; } } } } }