Files
hjha-server/PdkFriendServer/Logic/PdkGameMain_Method.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
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
2026-07-07 12:02:15 +08:00

469 lines
19 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}