Files
winapp/GameUnit.cpp
2026-06-12 22:37:02 +08:00

2066 lines
50 KiB
C++

//---------------------------------------------------------------------------
#include <System.StrUtils.hpp>
#include "GameUnit.h"
#include "GlobalUnit.h"
#include "UtilityUnit.h"
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma package(smart_init)
TSettings g_settings; //基本设置
TGameArray g_aGames;
int g_iRoad = 0; //全局路单/默认为六珠路
double g_fBalance = 0; //账户余额
bool g_bSimulate = true,
g_bShowSetting = true,
g_bGameOn = false,
g_bDeadPause = false, //全局爆缆暂停
g_bBetPause = false; //总体止赢止损暂停
int g_MinOnBet = 20, //最小注码
g_MaxOnBet = 50000; //最大注码
int g_nRBReport = 0; //实打流水上报
vector<TDot> g_aDots[4]; //资金图表数据 总赢利/模拟本金/账户余额
TIPGameArray g_aIPGames;
//---------------------------------------------------------------------------
int __fastcall Vid2Gid(String vid)
{
int id = 0;
if(g_iPlatform==PF_PA){
String sNum = vid.SubString(2,vid.Length()-1);
TryStrToInt(sNum, id);
if(id>0){
if(vid[1]=='D') id += 100;
else if(vid[1]=='M') id += 200;
else if(vid[1]=='P') id += 300;
else if(vid[1]=='E') id += 400;
else if(vid[1]!='N') id += (vid[1]-'A'+5) * 100;
}
}
else{
id = vid.ToInt();
}
return id;
}
/////////////////////////////////////////////////////////////////////////////
// TRankChip
TRankChip::TRankChip()
{
bWait = iType = 0;
pPolicy = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TRankChip::SetPolicy(TChipPolicy* pCP)
{
if(pPolicy!=pCP){
pPolicy = pCP;
Reset();
}
}
/////////////////////////////////////////////////////////////////////////////
// TTierChip
TTierChip::TTierChip()
{
iType = KIND_CHIP_HAN;
}
//---------------------------------------------------------------------------
void __fastcall TTierChip::Reset()
{
if(pPolicy){
TTierRow* pRow = (TTierRow*)pPolicy->aRows[0];
nRnkChip = pRow->chip;
nCount = pRow->hands;
iRank = nWLDiff = nAccChip = nLos = 0;
}
}
//---------------------------------------------------------------------------
int __fastcall TTierChip::HandleResult(int res, double wl)
{
if(res==1){
nWLDiff++;
nLos -= nRnkChip;
}
else if(res==2){
nWLDiff--;
nLos += nRnkChip;
}
else return iRank;
if(((TTierPolicy*)pPolicy)->bTierWinRet && iRank>0 && nWLDiff>0){ //高层赢回基
Reset();
}
else{
nCount--;
if(nCount==0){
TTierRow* pRow = (TTierRow*)pPolicy->aRows[iRank];
if(nWLDiff==0){//输赢平手 重打
nWLDiff = nLos = 0;
nCount = pRow->hands;
nRnkChip = nAccChip + pRow->chip;
return iRank;
}
if(nWLDiff>0){ //赢走向
iRank = pRow->iWin - 1;
nAccChip = 0; //净输累计清零
}
else{ //输走向
iRank = pRow->iLos - 1;
if(iRank>=0 && ((TTierPolicy*)pPolicy)->bTierAccChip){
if(iRank==0)
nAccChip = 0;
else{
nAccChip += nLos; //净输累加到下一层
if(nAccChip<0)
nAccChip = 0;
}
}
}
if(iRank>=0){
pRow = (TTierRow*)pPolicy->aRows[iRank];
nRnkChip = nAccChip + pRow->chip;
nCount = pRow->hands;
nWLDiff = nLos = 0;
}
}
else if(((TTierPolicy*)pPolicy)->bTierLos0){
if(nWLDiff<0) //输打0
nRnkChip = 0;
else{
TTierRow* pRow = (TTierRow*)pPolicy->aRows[iRank];
nRnkChip = nAccChip + pRow->chip;
}
}
}
return iRank;
}
/////////////////////////////////////////////////////////////////////////////
// TLevelChip
TLevelChip::TLevelChip(bool bG)
{
iType = KIND_CHIP_LEV;
bGlobal = bG;
}
//---------------------------------------------------------------------------
void __fastcall TLevelChip::CalcChip()
{
TLevelRow* pRow = (TLevelRow*)pPolicy->aRows[iRank];
nRnkChip = pRow->chip;
}
//---------------------------------------------------------------------------
void __fastcall TLevelChip::Reset()
{
if(pPolicy){
bWait = fWLDiff = iRank = 0;
CalcChip();
}
}
//---------------------------------------------------------------------------
int __fastcall TLevelChip::HandleResult(int res, double wl)
{
if(iRank<0 || res==3 && !bWait)
return iRank;
fWLDiff += wl;
bool bLevel = false;
TLevelRow* pRow = (TLevelRow*)pPolicy->aRows[iRank];
if(bGlobal && !g_aGames.bFloat && !((TLevelPolicy*)pPolicy)->bInstant){//非立即升降
if(fWLDiff >= pRow->nCondWin || fWLDiff <= -pRow->nCondLos){ //达到升降条件
g_aGames.AllBetOff();
bWait = g_aGames.nBetted[2]>0; //等待结算
DebugPrint("wait count: %d", g_aGames.nBetted[2]);
}
else if(bWait){
bWait = false;
DebugPrint("恢复下注 %.2f", fWLDiff);
}
}
if(!bWait){
if(fWLDiff >= pRow->nCondWin){ //赢走向
iRank = pRow->iWin - 1;
bLevel = true;
}
else if(fWLDiff <= -pRow->nCondLos){ //输走向
iRank = pRow->iLos - 1;
bLevel = true;
}
}
else{
DebugPrint("等待结算 %.2f", fWLDiff);
}
if(bLevel && bGlobal && !g_aGames.bFloat && ((TLevelPolicy*)pPolicy)->bInstant)
g_aGames.AllBetOff();
CalcLevelChip(bLevel, res);
return iRank;
}
//---------------------------------------------------------------------------
void __fastcall TLevelChip::CalcLevelChip(bool bLevel, int res)
{
if(bLevel && iRank>=0){
fWLDiff = 0;
CalcChip();
if(bGlobal && !g_aGames.bFloat){
PostMessage(Application->MainFormHandle, UM_GLOBAL_BET, 0, 0);
DebugPrint("升降阶梯 %d", iRank);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// TComboChip
TComboChip::TComboChip(bool bG)
{
iType = KIND_CHIP_COM;
pRnkPolicy = NULL;
bGlobal = bG;
}
//---------------------------------------------------------------------------
void __fastcall TComboChip::CalcChip()
{
int nBaseChip = 0;
if(pRnkPolicy->kind==KIND_CHIP_RAN){
int mi = g_RandomChip.minChip,
ma = g_RandomChip.maxChip+1; //包含最大值
nBaseChip = mi + Random(ma - mi);
}
else
nBaseChip = ((TChipRow*)pRnkPolicy->aRows[iRnkSeq])->chip;
nRnkChip = nBaseChip * nRnkMul;
}
//---------------------------------------------------------------------------
void __fastcall TComboChip::Reset()
{
if(pPolicy){
bWait = false;
fWLDiff = iRank = iRnkSeq = 0;
TComboRow* pRow = (TComboRow*)pPolicy->aRows[iRank];
CheckComboRow(pRow);
pRnkPolicy = (TChipPolicy*)g_aChipPolicies[pRow->iPolicy];
nRnkMul = pRow->chip;
if(!bGlobal || g_aGames.bFloat)
CalcChip();
}
}
//---------------------------------------------------------------------------
void __fastcall TComboChip::CalcLevelChip(bool bLevel, int res)
{
if(bLevel){
if(iRank>=0){
TComboRow* pRow = (TComboRow*)pPolicy->aRows[iRank];
CheckComboRow(pRow);
pRnkPolicy = (TChipPolicy*)g_aChipPolicies[pRow->iPolicy];
nRnkMul = pRow->chip;
fWLDiff = iRnkSeq = 0;
if(bGlobal && !g_aGames.bFloat){
g_aGames.ResetRankSeq();
PostMessage(Application->MainFormHandle, UM_GLOBAL_BET, 0, 0);
DebugPrint("升降阶梯 %d", iRank);
}
else{
CalcChip();
}
}
}
else if(!bGlobal || g_aGames.bFloat){
if(pRnkPolicy->kind!=KIND_CHIP_RAN){
TChipRow* pCR = (TChipRow*)pRnkPolicy->aRows[iRnkSeq];
if(res==1)
iRnkSeq = pCR->iWin - 1;
else if(res==2)
iRnkSeq = pCR->iLos - 1;
if(iRnkSeq<0) //立即重置
iRnkSeq = 0;
}
CalcChip();
}
}
//---------------------------------------------------------------------------
int __fastcall TComboChip::GetComboChip(int& iRnk, int& iSeq)
{
if(bWait || iRank<0)
return -1;
if(iRnk!=iRank){
iRnk = iRank;
iSeq = 0;
}
int nBaseChip = 0;
if(pRnkPolicy->kind==KIND_CHIP_RAN){
int mi = g_RandomChip.minChip,
ma = g_RandomChip.maxChip+1; //包含最大值
nBaseChip = mi + Random(ma - mi);
}
else
nBaseChip = ((TChipRow*)pRnkPolicy->aRows[iSeq])->chip;
return nBaseChip * nRnkMul;
}
//---------------------------------------------------------------------------
int __fastcall TComboChip::GetRankSeq(int res, int iRnk, int iSeq)
{
if(res!=3 && iRnk==iRank && pRnkPolicy->kind!=KIND_CHIP_RAN){
TChipRow* pCR = (TChipRow*)pRnkPolicy->aRows[iSeq];
if(res==1)
iSeq = pCR->iWin - 1;
else
iSeq = pCR->iLos - 1;
if(iSeq<0) //立即重置
iSeq = 0;
}
return iSeq;
}
/////////////////////////////////////////////////////////////////////////////
// TWLDiffChip
TWLDiffChip::TWLDiffChip(bool bG)
{
iType = KIND_CHIP_WLD;
bGlobal = bG;
}
//---------------------------------------------------------------------------
void __fastcall TWLDiffChip::CalcChip()
{
TLevelRow* pRow = (TLevelRow*)pPolicy->aRows[iRank];
nRnkChip = pRow->chip;
}
//---------------------------------------------------------------------------
void __fastcall TWLDiffChip::Reset()
{
if(pPolicy){
bWait = nWLDiff = iRank = 0;
CalcChip();
}
}
//---------------------------------------------------------------------------
int __fastcall TWLDiffChip::HandleResult(int res, double wl)
{
if(iRank<0 || res==3 && !bWait)
return iRank;
if(res==1)
nWLDiff++;
else if(res==2)
nWLDiff--;
bool bLevel = false;
TLevelRow* pRow = (TLevelRow*)pPolicy->aRows[iRank];
if(bGlobal && !g_aGames.bFloat && !((TLevelPolicy*)pPolicy)->bInstant){//非立即升降
if(nWLDiff >= pRow->nCondWin || nWLDiff <= pRow->nCondLos){ //达到升降条件
g_aGames.AllBetOff();
bWait = g_aGames.nBetted[2]>0; //等待结算
DebugPrint("wait count: %d", g_aGames.nBetted[2]);
}
else if(bWait){
bWait = false;
DebugPrint("恢复下注 %d", nWLDiff);
}
}
if(!bWait){
if(nWLDiff >= pRow->nCondWin){ //赢走向
iRank = pRow->iWin - 1;
bLevel = true;
}
else if(nWLDiff <= pRow->nCondLos){ //输走向
iRank = pRow->iLos - 1;
bLevel = true;
}
}
else{
DebugPrint("等待结算 %d", nWLDiff);
}
if(bLevel){
if(bGlobal && !g_aGames.bFloat && ((TLevelPolicy*)pPolicy)->bInstant)
g_aGames.AllBetOff();
if(iRank>=0){
if(((TWLDiffPolicy*)pPolicy)->bIndie) //立即清零
nWLDiff = 0;
CalcChip();
if(bGlobal && !g_aGames.bFloat){
PostMessage(Application->MainFormHandle, UM_GLOBAL_BET, 0, 0);
DebugPrint("升降层级 %d", iRank);
}
}
}
return iRank;
}
/////////////////////////////////////////////////////////////////////////////
// TGame
TGame::TGame(int iG)
{
iGame = iG;
hTable = NULL;
pRankChip = NULL;
Reset();
char name[16];
sprintf(name, "%04d", iG);
pSema = new CSema(name, 1);
}
//---------------------------------------------------------------------------
TGame::~TGame()
{
for(int i=0; i<4; i++)
aMap[i].Clear();
ClearRankChip();
delete pSema;
}
//---------------------------------------------------------------------------
void __fastcall TGame::ClearRankChip()
{
if(pRankChip){
delete pRankChip;
pRankChip = NULL;
}
}
//---------------------------------------------------------------------------
TRankChip* __fastcall TGame::GetRankChip(int type)
{
if(pRankChip && !pRankChip->IsTypeOf(type))
ClearRankChip();
if(!pRankChip){
pRankChip = type==KIND_CHIP_HAN ? (TRankChip*)new TTierChip
: type==KIND_CHIP_LEV ? (TRankChip*)new TLevelChip
: type==KIND_CHIP_WLD ? (TRankChip*)new TWLDiffChip
: (TRankChip*)new TComboChip;
}
return pRankChip;
}
//---------------------------------------------------------------------------
void __fastcall TGame::ClearResults()
{
aRes.clear();
for(int i=0; i<4; i++){
aRoad[i].clear();
lastRoad[i] = 0;
aMap[i].Clear(); //清理图数据
}
memset(winCount, 0, sizeof(winCount));
}
//---------------------------------------------------------------------------
void __fastcall TGame::Reset()
{
profit = iState = iBet = nChip = iBetSeq = iChipSeq = 0;
gmstatus = timeout = countdown = 0;
bcard = pcard = "";
memset(seqCount, 0, sizeof(seqCount));
ClearResults();
aManBets.clear();
bRun = bRev = bReset = bBreak = bPause
= bReal = bIndPolicy = false;
nChipMul = iRoad = iBetPolicy = iChipPolicy = -1;
}
//---------------------------------------------------------------------------
void __fastcall TGame::ResetBet()
{
ClearBets();
iState = iBet = nChip = iBetSeq = iChipSeq = 0;
bReal = bReset = false;
aBets.clear();
if(pRankChip)
pRankChip->Reset();
}
//---------------------------------------------------------------------------
int __fastcall TGame::Color2Bet(TBetPolicy* pBP, char clr)
{
int bet = 0;
int s0 = aRoad[0].back(), //大路最后1列个数(假设为断)
sR = aRoad[0][aRoad[0].size() - pBP->road];
char c = s0==sR ? 1 : 2; //齐脚跳红
if(c==clr) //此处为红蓝
bet = lastRoad[0] ^ 0x3; //大路断
else
bet = lastRoad[0]; //大路连
return bet;
}
//---------------------------------------------------------------------------
void __fastcall TGame::CalcBet()
{
iBet = nChip = 0; //默认不下注
int iBP = iBetPolicy>=0 ? iBetPolicy : g_iBetPolicy;
TBetPolicy* pBP = (TBetPolicy*)g_aBetPolicies[iBP];
int uBP = iBetSeq >> 16,
uSeq = 0;
if(uBP!=pBP->id){ //改用ID判断避免方案删除带来问题
uBP = pBP->id;
aBets.clear();
}
if(!aBets.empty()){ //连续下注项
if(aBets[0]==0 || aBets[0]==4){
iBet = aBets[0];
}
else if(pBP->road<=1 || aBets[0]==3){ //珠盘/大路或打和
iBet = aBets[0]; //此处为庄闲和
}
else if(aRoad[0].size() >= pBP->road){//下三路
iBet = Color2Bet(pBP, aBets[0]);
}
}
else if(pBP->road==0){ //珠盘路
if(aRes.empty())
return;
if(pBP->kind==KIND_BET_DIF){ //庄闲差
int diff = winCount[0] - winCount[1];
int i = diff>=g_BPDiffBet.diff[0] ? 0
: diff<=-g_BPDiffBet.diff[1] ? 1
: -1;
if(i>=0){
vector<char> bets = TBetPolicy::ParseBet(g_BPDiffBet.bets[i]);
iBet = bets[0];
if(bets.size()>1){
for(int j=0; j<bets.size(); j++)
aBets.push_back(bets[j]);
}
}
}
else{
for(int i=0; i<pBP->aRows.size(); i++){ //按从上往下的顺序匹配
TBetRow* pRow = (TBetRow*)pBP->aRows[i];
bool bAllMatched = true;
int pos = aRes.size()-1; //最后一个位置开始
for(int j=pRow->cond.size()-1; j>=0; j--){ //从后往前匹配
int item = pRow->cond[j];
bool up = item & 0x80;
char ch = item & 0x3;
int num = (item & 0x7C) >> 2;
if(pos<0 || ch!=aRes[pos--]){ //个数不足或颜色不匹配
bAllMatched = false;
break;
}
bool bMatched = true;
for(int k=1; k<num; k++){
if(pos<0 || ch!=aRes[pos--]){//个数不足或颜色不匹配
bMatched = false;
break;
}
}
if(!bMatched){
bAllMatched = false;
break;
}
if(up){ //不定长
while(ch==aRes[pos]) pos--; //一直找到不同颜色
}
}
if(bAllMatched){ //匹配成功
iBet = pRow->bets[0];
if(pRow->bets.size()>1){
for(int j=0; j<pRow->bets.size(); j++)
aBets.push_back(pRow->bets[j]);
}
break;
}
}
}
}
else{
vector<char>& road = aRoad[pBP->road-1];
if(road.empty())
return;
if(pBP->kind==KIND_BET_ASK){ //庄闲问路
int size0 = aRoad[0].size();
if(size0<4) return; //不够列数
if(size0>=4){
char cl[3], sR,
s0 = aRoad[0].back(); //大路最后1列个数(假设为断)
for(int i=0; i<3; i++){
sR = aRoad[0][size0 - i - 2];
cl[i] = s0==sR ? 1 : 2;
}
if(cl[0]!=cl[1] || cl[1]!=cl[2]) //不同色
return;
if(lastRoad[0]==2 && cl[0]==1 || lastRoad[0]==1 && cl[0]==2) //庄全红/闲全蓝
iBet = g_BPAskBet.bet[0];
else if(lastRoad[0]==1 && cl[0]==1 || lastRoad[0]==2 && cl[0]==2) //闲全红/庄全蓝
iBet = g_BPAskBet.bet[1];
}
}
else{
for(int i=0; i<pBP->aRows.size(); i++){ //按从上往下的顺序匹配
TBetRow* pRow = (TBetRow*)pBP->aRows[i];
if(road.size()<pRow->cond.size()) //列数不足
continue;
bool bAllMatched = true;
char last = lastRoad[pBP->road-1];
int col = road.size()-1; //最后一列开始
for(int j=pRow->cond.size()-1; j>=0 && bAllMatched; j--){ //从后往前匹配
int item = pRow->cond[j];
bool up = item & 0x80;
char ch = item & 0x3;
int num = (item & 0x7C) >> 2;
if(ch==last && (up && road[col]>=num || !up && road[col]==num)){ //该列成功
col--; //匹配下一列
last ^= 0x3; //下一列的颜色
}
else
bAllMatched = false;;
}
if(bAllMatched){ //匹配成功
if(pRow->bets[0]==0 || pRow->bets[0]==4){
iBet = pRow->bets[0];
}
if(pBP->road==1 || pRow->bets[0]==3){
iBet = pRow->bets[0]; //此处为庄闲和
}
else if(aRoad[0].size() >= pBP->road){//下三路
iBet = Color2Bet(pBP, pRow->bets[0]);
}
if(pRow->bets.size()>1){
for(int j=0; j<pRow->bets.size(); j++)
aBets.push_back(pRow->bets[j]);
}
break;
}
}
}
}
iBetSeq = (uBP<<16) + aRes.size()+1;
}
//---------------------------------------------------------------------------
void __fastcall TGame::CalcChip()
{
int iCP = iChipPolicy>=0 ? iChipPolicy : g_iChipPolicy;
TChipPolicy* pCP = (TChipPolicy*)g_aChipPolicies[iCP];
bool bGlobalChip = !bIndPolicy && (g_aGames.bFloat || pCP->kind>=KIND_CHIP_LEV
&& pCP->kind<=KIND_CHIP_WLD
&& ((TLevelPolicy*)pCP)->bTotalDiff);
int& iCS = !bIndPolicy && g_aGames.bFloat ? g_aGames.iChipSeq : iChipSeq;
int uCP = iCS >> 20,
uCRnk = (iCS & 0xFF000) >> 12,
uCSeq = iCS & 0xFFF;
if(uCP!=pCP->id){ //改用ID判断避免方案删除带来问题
uCRnk = uCSeq = 0;
iCS = (pCP->id<<20);
if(pCP->kind>=KIND_CHIP_HAN && pCP->kind<=KIND_CHIP_WLD){
TRankChip* pRC = bGlobalChip ? g_aGames.GetRankChip(pCP->kind)
: GetRankChip(pCP->kind);
pRC->SetPolicy(pCP);
}
else{
if(bGlobalChip && g_aGames.pRankChip)
g_aGames.ClearRankChip();
else
ClearRankChip();
}
}
if(pCP->kind>=KIND_CHIP_HAN && pCP->kind<=KIND_CHIP_WLD){
TRankChip* pRC = bGlobalChip ? g_aGames.GetRankChip(pCP->kind)
: GetRankChip(pCP->kind);
if(pCP->kind==KIND_CHIP_COM && bGlobalChip && !g_aGames.bFloat){
nChip = ((TComboChip*)pRC)->GetComboChip(uCRnk, uCSeq);
if(nChip>=0)
iCS = (pCP->id<<20) + (uCRnk<<12) + uCSeq;
}
else
nChip = pRC->GetChip();
if(nChip>0 && pCP->kind!=KIND_CHIP_COM)
nChip *= nChipMul<0 ? g_nChipMul : nChipMul;
}
else if(pCP->kind==KIND_CHIP_RAN){
int mi = g_RandomChip.minChip,
ma = g_RandomChip.maxChip+1; //包含最大值
nChip = mi + Random(ma - mi);
}
else{
TChipRow* pRow = (TChipRow*)pCP->aRows[uCSeq];
nChip = pRow->chip * (bIndPolicy ? nChipMul : g_nChipMul); //乘上倍数
}
}
//---------------------------------------------------------------------------
int __fastcall TGame::CalcResult(int op)
{
int uBP = iBetSeq >> 16,
uBSeq = iBetSeq & 0xFFFF;
if(!iBet || !uBSeq)// || uBSeq>aRes.size() && op!=2)// || !nChip) 允许注码为0
return 0;
int dType = 0; //是否爆缆
int ret = 3;
double wl = 0;
if(op<2){ //非超时
int res = aRes[uBSeq-1];
if(!aBets.empty() && (!g_settings.bBetsNoTie || res!=3 || iBet==3) ){ //连续下注,不忽略和|结果非和|下注和,删除本项
aBets.erase(aBets.begin());
}
if(iBet==res){ //赢
ret = 1;
if(iBet==1)
wl = nChip * 0.95;
else if(iBet==2)
wl = nChip;
else
wl = nChip * 8;
}
else if(res!=3){ //输
ret = 2;
wl = -nChip;
}
else if(nChip>0){ //有效流水不计和
g_aGames.betData.amounts[0] -= nChip;
if(bReal){ //和 实打统计
g_aGames.betData.amounts[1] -= nChip; //实打流水
g_nRBReport -= nChip;
}
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_AMOUNT, 0);
}
TBetLog* pLog = NewBetLog();
pLog->ev = LOGEVT_RES;
pLog->op = ret;
pLog->num = wl;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
}
else if(op==3){//注单撤销
g_aGames.betData.amounts[0] -= nChip;
if(bReal){ //实打统计
g_aGames.betData.amounts[1] -= nChip; //实打流水
g_nRBReport -= nChip;
}
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_AMOUNT, 0);
TBetLog* pLog = NewBetLog();
pLog->ev = LOGEVT_QUASH;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
}
else if(op==2 && (g_aGames.bFloat || !g_aGames.pRankChip)){ //超时仅处理总体组合阶梯
return ret;
}
//处理注码步骤
int iCP = iChipPolicy>=0 ? iChipPolicy : g_iChipPolicy;
TChipPolicy* pCP = (TChipPolicy*)g_aChipPolicies[iCP];
bool bGlobalChip = !bIndPolicy && (g_aGames.bFloat || pCP->kind>=KIND_CHIP_LEV
&& pCP->kind<=KIND_CHIP_WLD
&& ((TLevelPolicy*)pCP)->bTotalDiff);
int& iCS = !bIndPolicy && g_aGames.bFloat ? g_aGames.iChipSeq : iChipSeq;
int uCP = iCS >> 20,
uCRnk = (iCS & 0xFF000) >> 12,
uCSeq = iCS & 0xFFF;
if(uCP!=pCP->id){
uCRnk = uCSeq = 0;
if(pCP->kind>=KIND_CHIP_HAN && pCP->kind<=KIND_CHIP_WLD){
TRankChip* pRC = bGlobalChip ? g_aGames.GetRankChip(pCP->kind)
: GetRankChip(pCP->kind);
pRC->SetPolicy(pCP);
}
else{
if(bGlobalChip && g_aGames.pRankChip)
g_aGames.ClearRankChip();
else
ClearRankChip();
}
}
else if(pCP->kind>=KIND_CHIP_HAN && pCP->kind<=KIND_CHIP_WLD){
TRankChip* pRC = bGlobalChip ? g_aGames.GetRankChip(pCP->kind) : GetRankChip(pCP->kind);
if(pCP->kind==KIND_CHIP_COM && bGlobalChip && !g_aGames.bFloat && op<2)
uCSeq = ((TComboChip*)pRC)->GetRankSeq(ret, uCRnk, uCSeq);
int rnk = (g_aGames.bFloat && g_aGames.iFloatGame!=iGame) ? uCRnk
: pRC->HandleResult(ret, wl);
if(rnk!=uCRnk){
uCRnk = rnk;
uCSeq = 0;
}
}
else if(pCP->kind==KIND_CHIP_NOR && (!g_aGames.bFloat || g_aGames.iFloatGame==iGame)){
TChipRow* pRow = (TChipRow*)pCP->aRows[uCSeq];
if(ret==1)
uCSeq = pRow->iWin - 1;
else if(ret==2)
uCSeq = pRow->iLos - 1;
}
if(uCSeq<0 || uCRnk<0){
dType = pCP->dead + 1;
uCRnk = uCSeq = 0;
g_aGames.betData.dead++;
if(!bGlobalChip){
TBetLog* pLog = NewBetLog();
pLog->ev = LOGEVT_DEAD;
pLog->op = pCP->dead;
pLog->num = pCP->deadPause;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
}
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MISC, 0);
}
if(op<=2) //撤销不更新iCS
iCS = (pCP->id<<20) + (uCRnk<<12) + uCSeq;
if(wl!=0){
profit += wl;
//模拟实打赢利统计
if(bReal){
g_aGames.betData.profits[4] += wl;
g_aGames.betData.profits[7] += wl;
}
else
g_aGames.betData.profits[6] += wl;
//当期赢利
g_aGames.betData.profits[3] += wl;
if(wl>0 && g_aGames.fCurrProfitPeak < g_aGames.betData.profits[3]) //更新当期赢利峰值
g_aGames.fCurrProfitPeak = g_aGames.betData.profits[3];
//总赢利及峰谷值
double profit = g_aGames.betData.profits[0] + wl;
g_aGames.betData.profits[0] = profit;
if(profit>g_aGames.betData.profits[1]){
g_aGames.betData.profits[1] = profit;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_PEAK, 1);
}
else if(profit<g_aGames.betData.profits[2]){
g_aGames.betData.profits[2] = profit;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_PEAK, 2);
}
}
if(op!=2 && wl>=0 && nChip>0){
if(g_settings.bSimAccOn){
bool bUpdate = false;
if(!bReal || g_settings.bSyncReal){ //赢跟和都要加本金
g_settings.fSimAcc += wl + nChip;
bUpdate = true;
}
if(bReal && g_bTesting){
g_fBalance += wl + nChip;
bUpdate = true;
}
if(bUpdate)
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_BALANCE, 0);
}
}
if(ret==1){
g_aGames.betData.counts[0]++;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_COUNT, 0);
int* seq = g_aGames.bFloat ? g_aGames.seqCount : seqCount;
seq[0]++;
if(seq[0] > g_aGames.betData.counts[2]){
g_aGames.betData.counts[2] = seq[0];
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_COUNT, 2);
}
seq[1] = 0;//连输终止
}
else if(ret==2){
g_aGames.betData.counts[1]++;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_COUNT, 1);
int* seq = g_aGames.bFloat ? g_aGames.seqCount : seqCount;
seq[1]++;
if(seq[1] > g_aGames.betData.counts[3]){
g_aGames.betData.counts[3] = seq[1];
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_COUNT, 3);
}
seq[0] = 0;//连赢终止
}
if(wl!=0)
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_BET_R, ret);
if(dType) ret += dType<<16;
return ret;
}
//---------------------------------------------------------------------------
void __fastcall TGame::HandleResult(int op)
{
timeout = 0;
if(!aManBets.empty()){ //处理手工下注
if(op==0){ //正常结算
int res = aRes.back();
double wl = 0;
for(int i=aManBets.size()-1; i>=0; i--){
TManBet& rMB = aManBets[i];
if(rMB.state==ST_BETTED){
if(res==1)
wl += rMB.chips[0] * 0.95 - rMB.chips[1] - rMB.chips[2];
else if(res==2)
wl += rMB.chips[1] - rMB.chips[0] - rMB.chips[2];
else if(res==3){ //和
wl += rMB.chips[2] * 8; // - rMB.chips[0] - rMB.chips[1];
int refund = rMB.chips[0] + rMB.chips[1]; //有效投注不计和
if(refund){
g_nRBReport -= refund;
g_aGames.betData.amounts[2] -= refund; //手工流水
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MAN, 1);
}
}
}
aManBets.pop_back();
}
if(hTable) PostMessage(hTable, UM_TAB_UPDATE, UPDATE_MANRES, wl);
if(wl!=0){
g_aGames.betData.profits[5] += wl;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MAN, 0);
}
}
else if(op==1){ //数据异常
aManBets.clear();
}
else if(op==3){ //注单撤销
for(int i=aManBets.size()-1; i>=0; i--){
TManBet& rMB = aManBets[i];
if(rMB.state==ST_BETTED){
int refund = rMB.chips[0] + rMB.chips[1] + rMB.chips[2]; //有效投注不计和
if(refund){
g_nRBReport -= refund;
g_aGames.betData.amounts[2] -= refund; //手工流水
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MAN, 1);
}
}
aManBets.pop_back();
}
}
}
if((iState==ST_BETTED || iState==ST_EXPIRED) && ((iBetSeq & 0xFFFF)<=aRes.size() || op>=2)){
if(iState==ST_BETTED){
if(g_aGames.nBetted[bReal]>0)
g_aGames.nBetted[bReal]--; //减少下注个数
if(!bIndPolicy && g_aGames.nBetted[2]>0)
g_aGames.nBetted[2]--; //全局计算下注个数
}
if(op==2)
iState = ST_EXPIRED;
else if(op==3)
iState = ST_QUASH;
else
iState = ST_PAID;
int ret = CalcResult(op);
if(g_bGameOn){
int dead = ret >> 16;
if(bRun && (op<2 || dead)){
int wl = ret & 0xFF;
//止赢止损
bool stop = false;
if(wl==1 && g_settings.bTableStopWin && profit>=g_settings.nTableStopWin //单桌止赢
|| wl==2 && g_settings.bTableStopLos && profit<=-g_settings.nTableStopLos){ //单桌止赢
stop = true;
TBetLog* pLog = NewBetLog();
pLog->ev = wl==1 ? LOGEVT_STOPWIN : LOGEVT_STOPLOS;
pLog->op = wl==1 ? g_settings.iTableWinOp : g_settings.iTableLosOp;
pLog->num = wl==1 ? g_settings.nTableWinPause : g_settings.nTableLosPause;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
}
//处理游台
bool bFloat = false;
if(g_aGames.bFloat && g_aGames.iFloatGame==iGame){
if((g_settings.iFloatMode & 1) && aBets.empty() //连续下注项结束换台
|| (g_settings.iFloatMode & 4) && wl==2 //输换台
|| (g_settings.iFloatMode & 8) && wl==1 //赢换台
|| (g_settings.iFloatMode & 16) && wl==3 //和换台
|| g_settings.bHaltBet && aRes.size()>=g_settings.nHaltBet){//开局X手后停止下注
aBets.clear();
g_aGames.SetSwitchable(true, iGame);
bFloat = true;
}
if(dead && g_bGameOn){
int pause = dead==3 ? ((TChipPolicy*)g_aChipPolicies[g_iChipPolicy])->deadPause : 0;
SendMessage(Application->MainFormHandle, UM_FLOAT_DEAD, dead-1, pause);
}
}
//处理爆缆
if(dead && (bIndPolicy || !g_aGames.bFloat)){
if(!bIndPolicy && g_aGames.pRankChip){
// DebugPrint("总体阶梯爆缆");
int pause = dead==3 ? ((TChipPolicy*)g_aChipPolicies[g_iChipPolicy])->deadPause : 0;
SendMessage(Application->MainFormHandle, UM_GLOBAL_DEAD, dead-1, pause);
}
else{
bReset = true;
if(dead==2) //新局重启
bBreak = true;
}
}
//处理止盈止损
if(stop){
bReset = true;
int iOp = wl==1 ? g_settings.iTableWinOp : g_settings.iTableLosOp;
ret += (iOp+1)<<24;
if(iOp==1) //新局重启
bBreak = true;
}
if(bFloat && !dead)
PostMessage(Application->MainFormHandle, UM_FLOAT_BET, 0, 0);
}
else if(g_aGames.bFloat && g_aGames.iFloatGame==iGame){
g_aGames.SetSwitchable(true, 0); //非强制换台
PostMessage(Application->MainFormHandle, UM_FLOAT_BET, 0, 0);
}
}
if(op!=2)
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, ret);
}
else if(iState==ST_PAID || iState==ST_NOBET){
iState = ST_INIT;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
}
if(op<2){
iBetSeq &= 0xFFFF0000;
if(hTable) PostMessage(hTable, UM_TAB_UPDATE, UPDATE_ROAD, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::ClearBets()
{
aManBets.clear();
if(iState==ST_BETTED || iState==ST_EXPIRED){
if(iState==ST_BETTED){
if(g_aGames.nBetted[bReal]>0)
g_aGames.nBetted[bReal]--; //减少下注个数
if(!bIndPolicy && g_aGames.nBetted[2]>0)
g_aGames.nBetted[2]--; //全局计算下注个数
}
iState = iBetSeq = 0;
timeout = 0;
}
}
//---------------------------------------------------------------------------
bool __fastcall TGame::CanBet()
{
return bRun && g_bGameOn && !bPause && !g_bBetPause && (bIndPolicy || !g_bDeadPause);
}
//---------------------------------------------------------------------------
void __fastcall TGame::GameOn()
{
if(g_settings.bInitBetChipByStart || g_aGames.bFloat) //挂机初始化/游台也要初始化
bReset = true;
if(g_settings.bInitTabProfitByStart){ //开始挂机重置台桌赢利
profit = 0;
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_RESET, 0);
}
if(g_settings.bInitClearTabLog) //开始挂机清空台桌下注记录
SendMessage(hTable, UM_LOG_UPDATE, -1, 0);
if(g_settings.bWaitNew && aRes.size()>0){ //挂机等待新局
bBreak = true;
}
else{
bBreak = false;
if(bRun && gmstatus==1 && timeout>4)
AutoBetOn();
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::GameOff()
{
AutoBetOff();
bReset = bBreak = false;
if(bPause){
bPause = false;
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_RESET, 3);
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::AutoBetOn(bool bR)
{
CMutexLock mutex(pSema);
if(iState>=ST_NOBET && iState<=ST_BETTED) //已下注
return;
if((iState==ST_PAID || iState==ST_QUASH) && gmstatus!=0 && gmstatus!=2){
iState = ST_INIT;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
}
if(bR) bReset = true;
if(aRes.empty() && bRun && g_bGameOn && (gmstatus==1 || gmstatus==12)){ //新局上报,不受暂停影响
bBreak = false;
if(iState!=ST_ROUND){
iState = ST_ROUND;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
TBetLog* pLog = NewBetLog();
pLog->ev = LOGEVT_ROUND;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
if(g_settings.bInitBetByGame){ //新局重置打法
iBet = iBetSeq = 0;
aBets.clear();
}
if(g_settings.bInitChipByGame){ //新局重置注码
nChip = iChipSeq = 0;
}
if(g_settings.bInitProfitByGame && profit!=0 //新局重置赢利
|| g_settings.bTableStopWin && profit>=g_settings.nTableStopWin //止赢重置
|| g_settings.bTableStopLos && profit<=-g_settings.nTableStopLos){ //止损重置
profit = 0;
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_RESET, 0);
}
}
if(aBets.empty()) //连续下注可从新局开始
return;
}
if(bBreak || gmstatus!=1 || !CanBet() || !g_bSimulate && timeout<3){ //非下注状态/暂停中/实打时间太短,放弃
return;
}
if(g_settings.bHoldBet && aRes.size()<g_settings.nHoldBet //开局X手后开始下注
|| g_settings.bHaltBet && aRes.size()>=g_settings.nHaltBet){ //开局X手后停止下注
return;
}
if(g_aGames.bFloat && !bIndPolicy && !g_aGames.CanFloatBet(iGame)){//游台是否能下注
return;
}
if(bReset)
ResetBet();
CalcBet();
if(g_aGames.bFloat && !bIndPolicy){
if(!g_aGames.CanFloatBet(iGame)){ //游台是否能下注
iBet = iBetSeq = bBreak = 0;
aBets.clear();
}
else if(iBet>0 && iBet<4){
g_aGames.SetSwitchable(false, iGame); //游台下注
}
else if(!g_aGames.bSwitchable && g_aGames.iFloatGame==iGame
&& aBets.size()==1 && (g_settings.iFloatMode & 1)){ //最后一项不打,强制换台
g_aGames.SetSwitchable(true, iGame);
}
}
if(iBet==0 || iBet==4){
if(!aBets.empty()){//连续下注 不打/局停不可取消
aBets.erase(aBets.begin()); //删除本项
iState = ST_NOBET;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
// TBetLog* pLog = NewBetLog();
// pLog->ev = LOGEVT_BET;
// pLog->op = iBet;
// SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
}
if(iBet==4)
bBreak = true;
return;
}
CalcChip();
if(nChip>=0){
iState = ST_BETSET;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
PostMessage(Application->MainFormHandle, UM_SETBET, iGame, 0);
if(nChip>g_aGames.betData.maxChip){ //最大下注金额
g_aGames.betData.maxChip = nChip;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MISC, 0);
}
}
//止赢止损后需重置赢利
if(g_settings.bTableStopWin && profit>=g_settings.nTableStopWin
|| g_settings.bTableStopLos && profit<=-g_settings.nTableStopLos){
profit = 0;
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_RESET, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::AutoBetOff(bool bB)
{
CMutexLock mutex(pSema);
if(iState==ST_BETSET || iState==ST_BETTING){ //下注超时或取消
iState = ST_CANCELED;
iBet = nChip = 0;
// iBetSeq &= 0xFFFF0000;
// aBets.clear();
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
}
// else if(!bRun)
// aBets.clear();
if(iState!=ST_BETTED && g_bGameOn && g_aGames.bFloat && !g_aGames.bSwitchable
&& g_aGames.iFloatGame==iGame){ //游台取消下注标志,以免阻塞下注
if(!bRun || (g_settings.iFloatMode & 1) && aBets.empty()){ //每注换台或本台停止
g_aGames.SetSwitchable(true, 0); //非强制换台
PostMessage(Application->MainFormHandle, UM_FLOAT_BET, 0, 0);
}
}
// if(iState==ST_NOBET){
// iState = ST_INIT;
// if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
// }
if(bB && aRes.size()>0) bBreak = true;
}
//---------------------------------------------------------------------------
void __fastcall TGame::BetResp(int res, int chips[])
{
if(chips){ //ABThread返回时仅手工下注会携带chips
for(int i=aManBets.size()-1; i>=0; i--){ //先匹配手工下注
TManBet& rMB = aManBets[i];
if(rMB.state==ST_BETTING){
if(g_iPlatform==PF_DB && res){ //DB平台下注失败无法匹配金额
bool bMatch = true;
if(chips[0] || chips[1] || chips[2]){
for(int c=0; c<3; c++){
if(!chips[c] && rMB.chips[c] || chips[c] && !rMB.chips[c]){
bMatch = false;
break;
}
}
}
if(!bMatch)
continue;
}
else if(memcmp(chips, rMB.chips, sizeof(rMB.chips))) //非DB平台或下注成功 需确认金额匹配
continue;
if(res==0){
rMB.state = ST_BETTED;
int amo = chips[0] + chips[1] + chips[2];
g_aGames.betData.amounts[2] += amo; //手工流水
g_nRBReport += amo;
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_MAN, 1);
}
else
aManBets.erase(aManBets.begin()+i); //失败删除
if(hTable) PostMessage(hTable, UM_TAB_UPDATE, UPDATE_MANBET, res);
return;
}
}
}
//未匹配到手工下注,再处理自动下注
if(iState==ST_BETTING){
iState = res==0 ? ST_BETTED : ST_FAILED;
if(hTable) PostMessage(hTable, UM_LOG_UPDATE, iState, res);
if(res==0){
g_aGames.nBetted[bReal]++; //增加下注个数
if(!bIndPolicy)
g_aGames.nBetted[2]++; //全局计算下注
TBetLog* pLog = NewBetLog();
pLog->ev = LOGEVT_BET;
pLog->op = iBet;
pLog->num = nChip;
SendMessage(Application->MainFormHandle, UM_LOG_UPDATE, 0, (long)pLog);
if(nChip>0){
g_aGames.betData.amounts[0] += nChip;
if(bReal){
g_aGames.betData.amounts[1] += nChip; //实打流水
g_nRBReport += nChip;
}
if(g_settings.bSimAccOn){
bool bUpdate = false;
if(!bReal || g_settings.bSyncReal){
g_settings.fSimAcc -= nChip;
bUpdate = true;
}
if(bReal && g_bTesting){
g_fBalance -= nChip;
bUpdate = true;
}
if(bUpdate)
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_BALANCE, 0);
}
PostMessage(Application->MainFormHandle, UM_STATE_UPDATE, STATE_AMOUNT, 0);
}
}
else{
if(g_bGameOn && g_aGames.bFloat && g_aGames.iFloatGame==iGame){ //游台取消下注标志,以免阻塞下注
g_aGames.SetSwitchable(true, 0); //非强制换台
PostMessage(Application->MainFormHandle, UM_FLOAT_BET, 0, 0);
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::Shuffle()
{
ClearResults();
bBreak = false;
if(bReset)
ResetBet();
else{
if(g_settings.bInitBetByGame){ //新局重置打法
iBet = iBetSeq = 0;
aBets.clear();
}
if(g_settings.bInitChipByGame){ //新局重置注码
nChip = iChipSeq = 0;
}
iState = ST_INIT;
}
if(g_settings.bInitProfitByGame && profit!=0 //新局重置赢利
|| g_settings.bTableStopWin && profit>=g_settings.nTableStopWin //止赢重置
|| g_settings.bTableStopLos && profit<=-g_settings.nTableStopLos){ //止损重置
profit = 0;
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_RESET, 0);
}
if(hTable){
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_ROAD, 0);
PostMessage(hTable, UM_LOG_UPDATE, iState, 0);
}
if(g_bGameOn && g_aGames.bFloat && g_aGames.iFloatGame==iGame
&& ((g_settings.iFloatMode & 2) //洗牌换台
|| (g_settings.iFloatMode & 1) && aBets.empty())){ //连注完换台被重置
aBets.clear();
g_aGames.SetSwitchable(true, iGame);
PostMessage(Application->MainFormHandle, UM_FLOAT_BET, 0, 0);
}
}
//---------------------------------------------------------------------------
int __fastcall TGame::ParseCard(int c)
{
if(!c) return -1;
int n = c & 15;
if( n>=10 ) n = 0;
return n;
}
//---------------------------------------------------------------------------
void __fastcall TGame::BuildRoadmap(char wt)
{
//大路
int size0 = aRoad[0].size();
if(wt!=3){
if(lastRoad[0]!=wt){ aRoad[0].push_back(1); size0++;}
else aRoad[0].back()++;
}
aMap[0].DrawMap(wt, lastRoad[0]);
if(wt!=3)
lastRoad[0] = wt;
else
return;
//下三路
int rc[5];
rc[0] = aRoad[0].back(); //最后1列个数
for(int i=1; i<5; i++)
rc[i] = size0>i ? aRoad[0][size0-i-1] : 0;
for(int i=1; i<4; i++){
if(!rc[i] || rc[0]==1 && !rc[i+1]) return;
char cl = rc[0]==1 ? (rc[1]==rc[i+1] ? 1 : 2) //齐脚跳画红、突脚跳画蓝
: (rc[0]<=rc[i] || rc[0]>=rc[i]+2 ? 1 : 2); //有对画红、无对画蓝、突脚连画红
if(lastRoad[i]!=cl) aRoad[i].push_back(1), size0++;
else aRoad[i].back()++;
aMap[i].DrawMap(cl, lastRoad[i]);
lastRoad[i] = cl;
}
}
//---------------------------------------------------------------------------
TBetLog* __fastcall TGame::NewBetLog()
{
TBetLog* pLog = new TBetLog;
pLog->ts = DateTimeToUnix(Now(), false);
strcpy(pLog->tno, ((AnsiString)vid).c_str());
return pLog;
}
//---------------------------------------------------------------------------
void __fastcall TGame::ManualBetOn(int chips[])
{
TManBet mb;
memcpy(mb.chips, chips, sizeof(mb.chips));
aManBets.push_back(mb);
PostMessage(Application->MainFormHandle, UM_SETBET, iGame, 0);
}
//---------------------------------------------------------------------------
void __fastcall TGame::ManualBetOff()
{
for(int i=aManBets.size()-1; i>=0; i--){
TManBet& mb = aManBets[i];
if(mb.state!=ST_BETTED){
aManBets.erase(aManBets.begin()+i);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TGame::ResetIP()
{
if(bIndPolicy){
bIndPolicy = false;
nChipMul = iRoad = iBetPolicy = iChipPolicy = -1;
if(hTable)
PostMessage(hTable, UM_TAB_UPDATE, UPDATE_IP, 0);
// g_aIPGames.DelGame(this);
}
}
/////////////////////////////////////////////////////////////////////////////
//TRoadmap
TRoadmap::TRoadmap()
{
Clear();
}
//---------------------------------------------------------------------------
void __fastcall TRoadmap::Clear()
{
for(int i=0; i<aCols.size(); i++)
delete aCols[i];
aCols.clear();
iRoot = iRow = iCol = -1;
bBend = false;
}
//---------------------------------------------------------------------------
void __fastcall TRoadmap::CheckColumn()
{
if(iCol==aCols.size()){
char* col = new char[6];
memset(col, 0, 6);
aCols.push_back(col);
}
}
//---------------------------------------------------------------------------
void __fastcall TRoadmap::DrawMap(char curr, char last)
{
bool bCheck = false;
if(curr==3){
if(iRoot<0){
iRoot = iCol = iRow = 0;
curr = 0x04;
bCheck = true;
}
else
curr = aCols[iCol][iRow] + 0x04;
}
else if(!last && iRoot>=0){ //前面只有和
curr += aCols[iCol][iRow];
}
else if(curr!=last){ //新列
++iRoot;
if(iCol<iRoot)
bCheck = true;
iCol = iRoot;
iRow = 0;
bBend = false;
}
else{
if(bBend){ //继续横向绘制
++iCol;
bCheck = true;
}
else{
if(iRow==5 || aCols[iCol][iRow+1]){ //转为横向绘制
++iCol;
bBend = true;
bCheck = true;
}
else
++iRow;
}
}
if(bCheck)
CheckColumn();
aCols[iCol][iRow] = curr;
}
/////////////////////////////////////////////////////////////////////////////
//TGameArray
TGameArray::TGameArray()
{
bFloat = iFloatGame = iChipSeq = runTime = 0;
fCurrProfitPeak = -1E20;
bSwitchable = true;
memset(seqCount, 0, sizeof(seqCount));
memset(nBetted, 0, sizeof(nBetted));
pRankChip = NULL;
pSema = new CSema("GameArray", 1);
}
//---------------------------------------------------------------------------
TGameArray::~TGameArray()
{
ClearAllGames();
ClearRankChip();
delete pSema;
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::ClearAllGames()
{
if(!empty()){
int s = size();
for( int i=0; i<s; i++ ){
delete at(i);
}
clear();
}
memset(nBetted, 0, sizeof(nBetted));
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::ClearRankChip()
{
CMutexLock mutex(pSema);
if(pRankChip){
delete pRankChip;
pRankChip = NULL;
}
iChipSeq = 0;
}
//---------------------------------------------------------------------------
TRankChip* __fastcall TGameArray::GetRankChip(int type)
{
CMutexLock mutex(pSema);
if(pRankChip && !pRankChip->IsTypeOf(type)){
delete pRankChip;
pRankChip = NULL;
}
if(!pRankChip){
pRankChip = type==KIND_CHIP_HAN ? (TRankChip*)new TTierChip
: type==KIND_CHIP_LEV ? (TRankChip*)new TLevelChip(true)
: type==KIND_CHIP_WLD ? (TRankChip*)new TWLDiffChip(true)
: (TRankChip*)new TComboChip(true);
}
return pRankChip;
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::Reset()
{
int s = size();
for( int i=0; i<s; i++ ){
at(i)->Reset();
}
betData.Reset();
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::GameOn()
{
if(g_settings.bInitCurProfitByStart)//重置当期赢利
fCurrProfitPeak = betData.profits[3] = betData.profits[6] = betData.profits[7] = 0;
else if(fCurrProfitPeak < betData.profits[3]) //重置当期赢利峰值
fCurrProfitPeak = betData.profits[3];
if(bFloat = g_settings.iFloatMode>0){
bSwitchable = true;
iChipSeq = iFloatGame = 0;
memset(seqCount, 0, sizeof(seqCount));
TChipPolicy* pCP = (TChipPolicy*)g_aChipPolicies[g_iChipPolicy];
if(pCP->kind>=KIND_CHIP_HAN && pCP->kind<=KIND_CHIP_WLD){
GetRankChip(pCP->kind)->SetPolicy(pCP);
if(g_settings.bInitBetChipByStart)
pRankChip->Reset();
}
}
else if(g_settings.bInitBetChipByStart){
ClearRankChip();
}
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::GameOff()
{
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::AllBetOff()
{
int s = size();
for( int i=0; i<s; i++ ){
TGame* pG = at(i);
if(pG->bRun && !pG->bIndPolicy)
pG->AutoBetOff();
}
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::ResetRankSeq()
{
int s = size();
for( int i=0; i<s; i++ ){
TGame* pG = at(i);
if(pG->bRun && !pG->bIndPolicy)
pG->iChipSeq &= 0xFFFFF000;
}
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::ResetRankChip()
{
iChipSeq = 0;
if(pRankChip){
pRankChip->Reset();
if(!bFloat)
ResetRankSeq();
}
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::ResetFloat()
{
bFloat = g_settings.iFloatMode>0;
iChipSeq = iFloatGame = 0;
bSwitchable = true;
memset(seqCount, 0, sizeof(seqCount));
if(pRankChip)
pRankChip->Reset();
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::SetSwitchable(bool bS, int iG)
{
CMutexLock mutex(pSema);
bSwitchable = bS;
iFloatGame = iG;
//检查是否仅一台在运行
if(bS && iG){
int nRun = 0;
for(int i=0; i<size(); i++){
if(!at(i)->bIndPolicy && at(i)->bRun){
nRun++;
if(nRun>=2)
break;
}
}
if(nRun<2) //只有一台,则允许下注
iFloatGame = 0;
}
}
//---------------------------------------------------------------------------
bool __fastcall TGameArray::CanFloatBet(int iG)
{
CMutexLock mutex(pSema);
return bSwitchable && iFloatGame!=iG //可换台非强制
|| !bSwitchable && iFloatGame==iG; //不可换台当前台
};
//---------------------------------------------------------------------------
void __fastcall TGameArray::Init(String sRooms)
{
ClearAllGames();
TStringDynArray arr = SplitString( sRooms, ";" );
for( int i=0; i<arr.Length; i++ ){
if(!arr[i].Length()) continue;
TStringDynArray subs = SplitString( arr[i], "," );
int iG = Vid2Gid(subs[0]);
if( iG>0 ){
TGame* pG = NULL;
int ind = FindGame(iG, pG );
if( !pG ){
pG = NewGame(iG, subs[g_iPlatform==PF_PA ? 0 : 1], ind);
pG->gmcode = subs[2];
pG->gmstatus = subs[3].ToInt(); //先设为结算,避免重复
if(pG->gmstatus==1)
pG->gmstatus = 2;
// else if(pG->gmstatus==2)
// pG->gmstatus = 0;
for(int i=1; i<=subs[4].Length(); i++){
int wt = subs[4][i]-'0';
if(wt==0) wt = 3;
pG->aRes.push_back(wt);
pG->winCount[wt-1]++;
pG->BuildRoadmap(wt);
}
}
}
}
}
//---------------------------------------------------------------------------
TGame* __fastcall TGameArray::NewGame(int iG, String vid, int ind)
{
CMutexLock mutex(pSema);
TGame* pGame = new TGame(iG);
pGame->vid = vid;
if(g_aIPGames.iPlatform!=g_iPlatform){
g_aIPGames.ClearAll();
}
else{
TIPGame* pIG = NULL;
g_aIPGames.FindGame(vid, pIG);
if(pIG){
pGame->bIndPolicy = true;
pGame->iBetPolicy = pIG->iBetPolicy;
pGame->iChipPolicy = pIG->iChipPolicy;
pGame->nChipMul = pIG->nChipMul;
pGame->iRoad = ((TBetPolicy*)g_aBetPolicies[pIG->iBetPolicy])->road;
pIG->pGame = pGame;
}
}
insert( begin()+ind, pGame );
return pGame;
}
//---------------------------------------------------------------------------
void __fastcall TGameArray::SetCountDown(String s)
{
TStringDynArray arr = SplitString( s, ";" );
for( int i=0; i<arr.Length; i++ ){
if(arr[i].IsEmpty()) continue;
TStringDynArray subs = SplitString( arr[i], "," );
int iG = subs[0].ToInt();
int cd = subs[1].ToInt();
if( iG>0 && cd>=0 ){
TGame* pG = NULL;
int ind = FindGame(iG, pG );
if(pG){
int st = subs[2].ToInt();
if(pG->countdown<st){
pG->countdown = st;
if(pG->gmstatus==1){
pG->timeout = cd ? cd + 2 : 0;
if(pG->hTable) PostMessage(pG->hTable, UM_TAB_UPDATE, UPDATE_TIME, 0);
}
}
}
}
}
}
//---------------------------------------------------------------------------
TGame* __fastcall TGameArray::GetGame(int iG)
{
TGame * pG = NULL;
FindGame( iG, pG );
return pG;
}
//---------------------------------------------------------------------------
int __fastcall TGameArray::FindGame(int iG, TGame*& pGame)
{
CMutexLock mutex(pSema);
int middle, front=0, rear=size()-1;
int index = -1;
while( front<=rear ){
if( at(front)->iGame == iG ){
index = front;
pGame = at(front);
break;
}
if( at(rear)->iGame == iG ){
index = rear;
pGame = at(rear);
break;
}
middle = (front+rear)/2;
if( at(middle)->iGame == iG ){
index = middle;
pGame = at(middle);
break;
}
else if( at(middle)->iGame < iG )
front=middle+1;
else
rear=middle-1;
}
if( front>rear )
index = front;
return index;
}
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//TIPGameArray
TIPGameArray::~TIPGameArray()
{
ClearAll();
}
//---------------------------------------------------------------------------
void __fastcall TIPGameArray::ClearAll()
{
if(!empty()){
int s = size();
for( int i=0; i<s; i++ ){
delete at(i);
}
clear();
}
}
//---------------------------------------------------------------------------
int __fastcall TIPGameArray::FindGame(String vid, TIPGame*& pIG)
{
int middle, front=0, rear=size()-1;
int index = -1;
while( front<=rear ){
if( at(front)->vid == vid ){
index = front;
pIG = at(front);
break;
}
if( at(rear)->vid == vid ){
index = rear;
pIG = at(rear);
break;
}
middle = (front+rear)/2;
if( at(middle)->vid == vid ){
index = middle;
pIG = at(middle);
break;
}
else if( at(middle)->vid < vid )
front=middle+1;
else
rear=middle-1;
}
if( front>rear )
index = front;
return index;
}
//---------------------------------------------------------------------------
void __fastcall TIPGameArray::AddGame(TGame* pG)
{
if(iPlatform!=g_iPlatform)
iPlatform = g_iPlatform;
TIPGame* pIG = NULL;
int ind = FindGame(pG->vid, pIG);
if(!pIG){
insert(begin()+ind, new TIPGame(pG));
}
else{
pIG->iBetPolicy = pG->iBetPolicy;
pIG->iChipPolicy = pG->iChipPolicy;
pIG->nChipMul = pG->nChipMul;
}
}
//---------------------------------------------------------------------------
void __fastcall TIPGameArray::DelGame(TGame* pG)
{
TIPGame* pIG = NULL;
int ind = FindGame(pG->vid, pIG);
if(pIG){
delete pIG;
erase(begin()+ind);
}
}
//---------------------------------------------------------------------------
void __fastcall TIPGameArray::AddIPGame(String v, int b, int c, int m)
{
if(iPlatform!=g_iPlatform)
iPlatform = g_iPlatform;
TIPGame* pIG = NULL;
int ind = FindGame(v, pIG);
if(!pIG){
insert(begin()+ind, new TIPGame(v, b, c, m));
}
}
//---------------------------------------------------------------------------