6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
469 lines
19 KiB
C#
469 lines
19 KiB
C#
using GameData;
|
||
using MrWu.Debug;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using GameFix.Poker;
|
||
using GameFix.PaoDeKuaiF;
|
||
using GameMessage;
|
||
using GameMessage.PaoDeKuaiF;
|
||
|
||
namespace PdkFriendServer.Logic
|
||
{
|
||
public partial class PdkGameMain
|
||
{
|
||
/// <summary>
|
||
/// 获取黑桃3的位置,如果都没有黑桃3那就取黑桃4
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
byte GetHeiTao3Pos()
|
||
{
|
||
byte result = 0;
|
||
for (byte carId = 3; carId < 14; carId++)
|
||
{//从黑桃3开始找,没有找到就依次往上查找
|
||
for (byte i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
for (int j = GamePack.CardPack.Cards[i].CardInfos.Length - 1; j >= 0; j--)
|
||
{
|
||
if (GamePack.CardPack.Cards[i].CardInfos[j].Flower != 1) continue;
|
||
if (GamePack.CardPack.Cards[i].CardInfos[j].GameNum > carId) break;
|
||
if (GamePack.CardPack.Cards[i].CardInfos[j].GameNum == carId)
|
||
{
|
||
result = (byte)(i + 1);
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取红桃十的玩家位置
|
||
/// </summary>
|
||
/// <returns>0没有玩家有红桃十 大于0就是改位置的玩家</returns>
|
||
byte GetHongTaoShiPos()
|
||
{
|
||
byte result = 0;
|
||
for (byte i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
for (int j = GamePack.CardPack.Cards[i].CardInfos.Length - 1; j >= 0; j--)
|
||
{
|
||
if (GamePack.CardPack.Cards[i].CardInfos[j].Flower != 2) continue;
|
||
if (GamePack.CardPack.Cards[i].CardInfos[j].GameNum == 10)
|
||
{
|
||
result = (byte)(i + 1);
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找下一个玩家的位置
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <returns></returns>
|
||
byte GetNextPos(byte pos)
|
||
{
|
||
if (pos <= 0) throw new Exception("参数错误" + pos);
|
||
byte result = (byte)(pos + 1);
|
||
if (result > GamePack.Info.PlayNum)
|
||
{
|
||
result = 1;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 游戏是否结束
|
||
/// </summary>
|
||
/// <returns>true游戏结束 false游戏没有结束</returns>
|
||
bool IsGameOver(byte chupaoPos)
|
||
{
|
||
if (GamePack.Info.BaoPos > 0 && GamePack.Info.ShenYuCard[GamePack.Info.BaoPos - 1] == 0)
|
||
{
|
||
//包庄人的牌出完了,游戏结束
|
||
GamePack.Info.OverPos = GamePack.Info.BaoPos;
|
||
return true;
|
||
}
|
||
|
||
//如果是包庄的话,出牌的人
|
||
if (GamePack.Info.BaoPos > 0 && chupaoPos > 0)
|
||
{
|
||
var b = GamePack.Info.BaoPos != chupaoPos; //如果出牌的位置和包庄位置不一样。就说明被别人给压牌了,游戏结束
|
||
if (b)
|
||
{
|
||
GamePack.Info.OverPos = chupaoPos; //记录压他牌的人位置
|
||
}
|
||
return b;
|
||
}
|
||
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
if (GamePack.Info.ShenYuCard[i] <= 0)
|
||
{ //只要有一个玩家的牌出完就结束
|
||
GamePack.Info.OverPos = (byte)(i + 1);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查出牌包内容
|
||
/// </summary>
|
||
/// <param name="pack"></param>
|
||
/// <returns></returns>
|
||
public bool CheckChuPai(PlayOutCardPdkF payCard)
|
||
{
|
||
if (payCard.Pos <= 0 || payCard.Pos > 3) return false;
|
||
if (PokerLogic.CheckSameId(payCard.Ids))
|
||
{
|
||
Log($"玩家出了相同ID的牌型,{payCard}", DebugLevel.Error);
|
||
return false;
|
||
}
|
||
if (GamePack.Info.MaxPlayCard.GameNum == 0 && payCard.Type == CardType1.None) return false; //第一个出牌人不能出不要
|
||
if (GamePack.Info.MaxPlayCard.GameNum > 0 && payCard.Type == CardType1.None)
|
||
{
|
||
if (!Rule.BiYa && !Rule.XiaJiaBaoDan) return true; //不是必压的情况下,并且没有勾选下家报单,之前有人出牌,再出个不要可以出
|
||
//不必压,但是勾选下家报单,之前出的不是单张,这个时候可以出不要。
|
||
if (!Rule.BiYa && Rule.XiaJiaBaoDan && GamePack.Info.MaxPlayCard.Type != CardType1.DanZhang) return true;
|
||
if (!Rule.BiYa && Rule.XiaJiaBaoDan && GamePack.Info.ShenYuCard[GetNextPos(payCard.Pos) - 1] != 1) return true;
|
||
}
|
||
if (!CheckPaiIsInHand(payCard.Ids, payCard.Pos)) return false;
|
||
if (!Rule.AAAIsZhaDan && payCard.Type == CardType1.ZhaDan && payCard.GameNum == 14) return false; //3个A不是炸弹
|
||
if (!Rule.SiDai2 && payCard.Type == CardType1.SiDai2) return false;
|
||
if (!Rule.SiDai3 && payCard.Type == CardType1.SiDai3) return false;
|
||
//if (!Rule.BiYa && GamePack.Info.MaxPlayCard.GameNum > 0 && payCard.Type == CardType.None) return true; //如果之前有人出牌,再出个不要可以出
|
||
if ((Rule.BiYa ||
|
||
(Rule.XiaJiaBaoDan && GamePack.Info.MaxPlayCard.Type == CardType1.DanZhang && GamePack.Info.ShenYuCard[GetNextPos(payCard.Pos) - 1] == 1))
|
||
&& payCard.Type == CardType1.None)
|
||
{ //如果是必压,玩家出了不要,检查一下玩家有没有必上一家大的牌
|
||
return !PdkCardAlgorithm.CheckHaveBigger(GamePack.Info.MaxPlayCard, GamePack.CardPack.Cards[payCard.Pos - 1].CardInfos.Where(x => x.GameState == 1).ToArray(),
|
||
GamePack.CardPack.Cards[GamePack.Info.MaxPlayCard.Pos - 1].CardInfos, Rule.AAAIsZhaDan);
|
||
}
|
||
int count = GamePack.Info.ShenYuCard[payCard.Pos - 1];
|
||
//单张、对子、三带二、顺子、连对、飞机带翅膀、炸弹,四带三、四带二
|
||
if (payCard.Type == CardType1.SanDai2 && count >= 5 && payCard.Ids.Length < 5) return false;
|
||
if (payCard.Type == CardType1.SiDai3 && count >= 7 && payCard.Ids.Length < 7) return false;
|
||
if (payCard.Type == CardType1.SiDai2 && count >= 6 && payCard.Ids.Length < 6) return false;
|
||
if (payCard.Type == CardType1.FeiJi)
|
||
{//如果飞机的张数不够就返回false
|
||
if (count >= 10 && payCard.Ids.Length < 10) return false;
|
||
var sanzhang = PokerLogic.GetFeiJiCount(GetCardByIds(payCard.Pos, payCard.Ids));
|
||
var c = sanzhang * 3 + sanzhang * 2;
|
||
if (count >= c && payCard.Ids.Length < c) return false;
|
||
var maxSanZahng = PokerLogic.GetFeiJiCount(GetCardByIds(GamePack.Info.MaxPlayCard.Pos, GamePack.Info.MaxPlayCard.Ids));
|
||
if (sanzhang < maxSanZahng) return false;
|
||
}
|
||
if (GamePack.Info.MaxPlayCard.GameNum == 0)
|
||
{
|
||
//如果最大的出牌人是没有值的话,然后当前人不是出不要就可以出下去。
|
||
return payCard.Type != CardType1.None;
|
||
}
|
||
if (GamePack.Info.MaxPlayCard.Type == payCard.Type)
|
||
{
|
||
if (payCard.Type == CardType1.DanZhang || payCard.Type == CardType1.DuiZi || payCard.Type == CardType1.ShunZi || payCard.Type == CardType1.LianDui)
|
||
{
|
||
return payCard.Ids.Length == GamePack.Info.MaxPlayCard.Ids.Length && payCard.GameNum > GamePack.Info.MaxPlayCard.GameNum;
|
||
}
|
||
else
|
||
{
|
||
return payCard.GameNum > GamePack.Info.MaxPlayCard.GameNum;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if (GamePack.Info.MaxPlayCard.Type != CardType1.ZhaDan)
|
||
{
|
||
return payCard.Type == CardType1.ZhaDan;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检测牌是否都在玩家手上
|
||
/// </summary>
|
||
/// <param name="Ids">要检测的牌ID集合</param>
|
||
/// <param name="pos">要检测哪个玩家的手牌</param>
|
||
/// <returns>true都在手上 false没有在手上</returns>
|
||
bool CheckPaiIsInHand(byte[] Ids, int pos)
|
||
{
|
||
if (pos <= 0 || pos > GamePack.Info.PlayNum) return false;
|
||
if (Ids == null || Ids.Length <= 0) return true; //没有牌不检测
|
||
pos--;
|
||
int count = 0;
|
||
foreach (var id in Ids)
|
||
{
|
||
foreach (var item in GamePack.CardPack.Cards[pos].CardInfos)
|
||
{
|
||
if (item.ID == id && item.GameState == 1)
|
||
{
|
||
count++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return count == Ids.Length;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 给某个玩家加炸弹,其他玩家减炸弹
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <param name="num"></param>
|
||
void AddZhaDanCount(int pos, int num)
|
||
{
|
||
for (int i = 0; i < GamePack.Info.ZhaDans.Length; i++)
|
||
{
|
||
if (i + 1 == pos)
|
||
{
|
||
GamePack.Info.ZhaDans[i] += num * (GamePack.Info.ZhaDans.Length - 1);
|
||
}
|
||
else
|
||
{
|
||
GamePack.Info.ZhaDans[i] -= num;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置朋友房规则
|
||
/// </summary>
|
||
public void SetFriendGz()
|
||
{
|
||
if (this.DeskGameDo == null) return;
|
||
var gz = this.DeskGameDo.GetRoomGz();
|
||
Rule = new PdkRule();
|
||
Rule.BiYa = true;//不必压
|
||
if (gz[0] == '0')
|
||
{
|
||
Rule.JingDianWanFa = true;
|
||
}
|
||
else if (gz[0] == '1')
|
||
{
|
||
Rule.Zhang15 = true;
|
||
}
|
||
else if (gz[0] == '2')
|
||
{
|
||
Rule.GuanPai = true;
|
||
Rule.BiYa = false;//不必压
|
||
}
|
||
if (gz[1] == '0')
|
||
{
|
||
Rule.ShouJu3 = true;
|
||
}
|
||
else if (gz[1] == '1')
|
||
{
|
||
Rule.MeiJu3 = true;
|
||
}
|
||
if (gz[2] == '0')
|
||
{
|
||
Rule.SiDai3 = true;
|
||
}
|
||
else if (gz[2] == '1')
|
||
{
|
||
Rule.SiDai2 = true;
|
||
}
|
||
if (gz[8] == '0')
|
||
{
|
||
GamePack.Info.PlayNum = 2;
|
||
}
|
||
else if (gz[8] == '1')
|
||
{
|
||
GamePack.Info.PlayNum = 3;
|
||
}
|
||
Rule.XianShenYuPai = gz[3] == '1';
|
||
Rule.HongTao10ZhaNiao = gz[4] == '1';
|
||
Rule.BaoZhuang = gz[5] == '1';
|
||
Rule.AAAIsZhaDan = gz[6] == '1';
|
||
Rule.XiaJiaBaoDan = gz[7] == '1';
|
||
Rule.ZhaDanDeFen = gz[9] == '1';
|
||
Rule.HeiTao3BiChu = gz[11] == '1';
|
||
switch (gz[10]) //设置托管
|
||
{
|
||
case '0':
|
||
Rule.TuoGuanNum = 0;
|
||
break;
|
||
case '1':
|
||
Rule.TuoGuanNum = 1;
|
||
break;
|
||
case '2':
|
||
Rule.TuoGuanNum = 3;
|
||
break;
|
||
case '3':
|
||
Rule.TuoGuanNum = 5;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 闹钟计时器
|
||
/// </summary>
|
||
public int TimeNum = 0;
|
||
|
||
/// <summary>
|
||
/// 包庄托管
|
||
/// </summary>
|
||
void BaoZhuangTuoGuan()
|
||
{
|
||
// var seat = GamePack.Info.WhoPlay - 1;
|
||
int count = 0;
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
var pl = this.DeskGameDo.desk[i];
|
||
if (pl != null && pl.isDePosit)
|
||
{
|
||
count++;
|
||
}
|
||
}
|
||
if (count == 0) return; //不需要托管
|
||
//GamePack.Info.PlayTuoGauan[seat] = 1;
|
||
for (byte i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
var pl = this.DeskGameDo.desk[i];
|
||
if (GamePack.Info.BaoZhuang[i] == 0 && pl != null && pl.isDePosit)
|
||
{
|
||
GamePack.Info.BaoZhuang[i] = 2;
|
||
}
|
||
}
|
||
Debug.Info("包庄托管!GameDo");
|
||
GameDo();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回黑桃三的下标
|
||
/// </summary>
|
||
/// <param name="cards">可以出的牌组合</param>
|
||
/// <param name="index">返回黑桃三的下标</param>
|
||
/// <returns>false没有黑桃三 true有黑桃三</returns>
|
||
bool GetHei3Index(List<List<TCardInfoPdkF>> cards, out int index)
|
||
{
|
||
index = -1;
|
||
try
|
||
{
|
||
|
||
if (cards == null || cards.Count <= 0) return false;
|
||
bool isfirstChu = GamePack.Info.PlayNum == 2 ? GamePack.Info.ShenYuCard[0] == GamePack.Info.ShenYuCard[1]
|
||
: GamePack.Info.ShenYuCard[0] == GamePack.Info.ShenYuCard[1] && GamePack.Info.ShenYuCard[1] == GamePack.Info.ShenYuCard[2];
|
||
if (!isfirstChu) return false; //如果不是第一次出牌, 就不管
|
||
for (int i = 0; i < cards.Count; i++)
|
||
{
|
||
if (cards[i] == null || cards[i].Count <= 0) continue;
|
||
if (cards[i][0].Flower == 1 && cards[i][0].GameNum == 3)
|
||
{
|
||
index = i;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.Error($"返回黑桃三的下标 msg:{e.Message},code:{e.StackTrace}");
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打牌托管
|
||
/// </summary>
|
||
void DaPaiTuoGuan()
|
||
{
|
||
var seat = GamePack.Info.WhoPlay - 1;
|
||
var pl = this.DeskGameDo.desk[seat];
|
||
if (pl == null) return; //不需要托管
|
||
if (Rule.BiYa)
|
||
{
|
||
if (pl.outline == 0)
|
||
{//玩家没有离线
|
||
if (!pl.isDePosit) return; //不需要托管
|
||
}
|
||
else
|
||
{//玩家离线
|
||
if (!pl.isDePosit && GamePack.Info.MaxPlayCard.GameNum <= 0) return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!pl.isDePosit) return; //不需要托管
|
||
}
|
||
//GamePack.Info.PlayTuoGauan[seat] = 1; //加这个是为了兼容老客户端
|
||
if (GamePack.Info.MaxPlayCard.GameNum <= 0)
|
||
{ //托管先出
|
||
var tishi = PdkCardAlgorithm.GetTipCard(GamePack.Info.MaxPlayCard,
|
||
GamePack.CardPack.Cards[GamePack.Info.WhoPlay - 1].CardInfos.Where(x => x.GameState == 1).ToArray(),
|
||
GamePack.Info.MaxPlayCard.Pos == 0 ? null : GamePack.CardPack.Cards[GamePack.Info.MaxPlayCard.Pos - 1].CardInfos,
|
||
Rule.AAAIsZhaDan);
|
||
var idx = Rule.XiaJiaBaoDan && GamePack.Info.ShenYuCard[GetNextPos(GamePack.Info.WhoPlay) - 1] == 1 ? tishi.Count - 1 : 0;
|
||
if (Rule.HeiTao3BiChu && logicMemory.WarCount == 0)
|
||
{//如果首局黑桃三首次必出,第一次出牌就必出黑桃三
|
||
var h3 = GetHei3Index(tishi, out var idx3);
|
||
if (h3 && idx3 >= 0)
|
||
{
|
||
idx = idx3;
|
||
}
|
||
}
|
||
var payCard = new PlayOutCardPdkF();
|
||
payCard.Pos = (byte)GamePack.Info.WhoPlay;
|
||
payCard.Type = CardType1.DanZhang;
|
||
payCard.GameNum = tishi[idx][0].GameNum;
|
||
payCard.Ids = tishi[idx].Select(x => x.ID).ToArray();
|
||
Log($"who:{GamePack.Info.WhoPlay}先出 ,托管出的牌:{payCard}");
|
||
GamePack.Info.ActivePlayCard = payCard;
|
||
}
|
||
else
|
||
{
|
||
var shoupai = GamePack.CardPack.Cards[GamePack.Info.WhoPlay - 1].CardInfos.Where(x => x.GameState == 1).ToArray();
|
||
var tishi = PdkCardAlgorithm.GetTipCard(GamePack.Info.MaxPlayCard,
|
||
shoupai,
|
||
GamePack.Info.MaxPlayCard.Pos == 0 ? null : GamePack.CardPack.Cards[GamePack.Info.MaxPlayCard.Pos - 1].CardInfos,
|
||
Rule.AAAIsZhaDan, true);
|
||
var payCard = new PlayOutCardPdkF();
|
||
payCard.Pos = (byte)GamePack.Info.WhoPlay;
|
||
if (tishi == null || tishi.Count <= 0)
|
||
{
|
||
payCard.Type = CardType1.None;
|
||
}
|
||
else
|
||
{
|
||
if (pl.outline == 1 && !pl.isDePosit) return; //玩家离线并且没有到托管时间
|
||
payCard.Type = PdkCardAlgorithm.IsZhaDan(tishi[tishi.Count - 1].ToArray(), Rule.AAAIsZhaDan) ? CardType1.ZhaDan : GamePack.Info.MaxPlayCard.Type;
|
||
var idx = Rule.XiaJiaBaoDan && GamePack.Info.ShenYuCard[GetNextPos(GamePack.Info.WhoPlay) - 1] == 1 && payCard.Type == CardType1.DanZhang ? 0 : tishi.Count - 1;
|
||
payCard.GameNum = tishi[idx][0].GameNum;
|
||
payCard.Ids = tishi[idx].Select(x => x.ID).ToArray();
|
||
if (payCard.Type == CardType1.FeiJi || payCard.Type == CardType1.SanDai2)
|
||
{
|
||
int n = (payCard.Ids.Length / 3) * 2;
|
||
var chaCard = shoupai.Except(tishi[idx]);
|
||
List<TCardInfoPdkF> chupais = new List<TCardInfoPdkF>(16);
|
||
chupais.AddRange(tishi[idx]);
|
||
chupais.AddRange(chaCard.Reverse().Take(n));
|
||
payCard.Ids = chupais.Select(x => x.ID).ToArray();
|
||
}
|
||
}
|
||
Log($"who:{GamePack.Info.WhoPlay}跟牌 pai:{GamePack.Info.MaxPlayCard}托管出的牌:{payCard}");
|
||
GamePack.Info.ActivePlayCard = payCard;
|
||
}
|
||
Debug.Info("打牌托管GameDo!");
|
||
GameDo();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 游戏临时加载的初始化
|
||
/// </summary>
|
||
public void LoadInit()
|
||
{
|
||
logicMemory.Init();
|
||
TimeNum = 0;
|
||
}
|
||
}
|
||
}
|