You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

387 lines
15 KiB

/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "pangea777.h"
void pangea_fold(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player)
{
uint8_t tmp;
//printf("player.%d folded\n",player); //getchar();
tp->hand.handmask |= (1 << player->ind);
player->betstatus = CARDS777_FOLD;
player->action = CARDS777_FOLD;
tmp = player->ind;
pangea_summaryadd(myinfo,tp,CARDS777_FOLD,&tmp,sizeof(tmp),(void *)&player->bets,sizeof(player->bets));
}
int32_t pangea_bet(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player,int64_t bet,int32_t action)
{
uint64_t sum; uint8_t tmp; struct hand_info *hand = &tp->hand;
if ( Debuglevel > 2 )
printf("PANGEA_BET[%d] <- %.8f\n",player->ind,dstr(bet));
if ( player->betstatus == CARDS777_ALLIN )
return(CARDS777_ALLIN);
else if ( player->betstatus == CARDS777_FOLD )
return(CARDS777_FOLD);
if ( bet > 0 && bet >= player->balance )
{
bet = player->balance;
player->betstatus = action = CARDS777_ALLIN;
}
else
{
if ( bet > hand->betsize && bet > hand->lastraise && bet < (hand->lastraise<<1) )
{
printf("pangea_bet %.8f not double %.8f, clip to lastraise\n",dstr(bet),dstr(hand->lastraise));
bet = hand->lastraise;
action = CARDS777_RAISE;
}
}
sum = player->bets;
if ( sum+bet < hand->betsize && action != CARDS777_ALLIN )
{
pangea_fold(myinfo,tp,player);
action = CARDS777_FOLD;
if ( Debuglevel > 2 )
printf("player.%d betsize %.8f < hand.betsize %.8f FOLD\n",player->ind,dstr(bet),dstr(hand->betsize));
return(action);
}
else if ( bet >= 2*hand->lastraise )
{
hand->lastraise = bet;
hand->numactions = 0;
if ( action == CARDS777_CHECK )
{
action = CARDS777_FULLRAISE; // allows all players to check/bet again
if ( Debuglevel > 2 )
printf("FULLRAISE by player.%d\n",player->ind);
}
}
sum += bet;
if ( sum > hand->betsize )
{
hand->numactions = 0;
hand->betsize = sum, hand->lastbettor = player->ind;
if ( sum > hand->lastraise && action == CARDS777_ALLIN )
hand->lastraise = sum;
else if ( action == CARDS777_CHECK )
action = CARDS777_BET;
}
if ( bet > 0 && action == CARDS777_CHECK )
action = CARDS777_CALL;
tmp = player->ind;
pangea_summaryadd(myinfo,tp,action,&tmp,sizeof(tmp),(void *)&bet,sizeof(bet));
player->balance -= bet, player->bets += bet;
if ( Debuglevel > 2 )
printf("player.%d: player.%d BET %f -> balances %f bets %f\n",tp->priv.myind,player->ind,dstr(bet),dstr(player->balance),dstr(player->bets));
return(action);
}
void pangea_antes(struct supernet_info *myinfo,struct table_info *tp)
{
int32_t i,n,N; struct player_info *p; uint64_t threshold; int32_t handid;
N = tp->G.numactive;
for (i=0; i<tp->G.N; i++)
{
tp->G.P[i].ind = i;
if ( (tp->snapshot[i]= tp->G.P[i].balance) <= 0 )
pangea_fold(myinfo,tp,&tp->G.P[i]);
}
handid = tp->numhands - 1;
pangea_summaryadd(myinfo,tp,CARDS777_SNAPSHOT,(void *)&handid,sizeof(handid),(void *)tp->snapshot,sizeof(uint64_t)*CARDS777_MAXPLAYERS);
if ( tp->G.ante != 0 )
{
for (i=0; i<N; i++)
{
if ( (p= tp->active[i]) != 0 )
{
if ( p->balance < tp->G.ante )
pangea_fold(myinfo,tp,p);
else pangea_bet(myinfo,tp,p,tp->G.ante,CARDS777_ANTE);
} else printf("unexpected null player ptr\n");
}
}
for (i=n=0; i<N; i++)
{
if ( i == 0 )
threshold = (tp->G.bigblind >> 1) - 1;
else if ( i == 1 )
threshold = tp->G.bigblind - 1;
else threshold = 0;
if ( (p= tp->active[i]) != 0 && p->balance < threshold )
pangea_fold(myinfo,tp,p);
else n++;
}
if ( n < 2 )
printf("pangea_antes not enough players n.%d\n",n);
else
{
pangea_bet(myinfo,tp,tp->active[0],(tp->G.bigblind>>1),CARDS777_SMALLBLIND);
pangea_bet(myinfo,tp,tp->active[1],tp->G.bigblind,CARDS777_BIGBLIND);
}
}
void pangea_checkantes(struct supernet_info *myinfo,struct table_info *tp)
{
int64_t bets[CARDS777_MAXPLAYERS+1]; int32_t i,N = tp->G.numactive; struct hand_info *hand = &tp->hand;
pangea_snapshot(tp,bets);
for (i=0; i<N; i++)
{
//printf("%.8f ",dstr(dp->balances[i]));
if ( bets[i] != 0 )
break;
}
if ( i == N && hand->checkprod.txid != 0 )
{
for (i=0; i<N; i++)
if ( bets[i] != 0 )
break;
if ( i == N )
{
//printf("i.%d vs N.%d call antes\n",i,N);
pangea_antes(myinfo,tp);
} else printf("bets i.%d\n",i);
}
}
uint64_t pangea_winnings(int32_t player,uint64_t *pangearakep,uint64_t *hostrakep,uint64_t total,int32_t numwinners,int32_t rakemillis,uint64_t maxrake)
{
uint64_t split,pangearake,rake;
if ( numwinners > 0 )
{
split = (total * (1000 - rakemillis)) / (1000 * numwinners);
pangearake = (total - split*numwinners);
if ( pangearake > maxrake )
{
pangearake = maxrake;
split = (total - pangearake) / numwinners;
pangearake = (total - split*numwinners);
}
}
else
{
split = 0;
pangearake = total;
}
if ( rakemillis > PANGEA_MINRAKE_MILLIS )
{
rake = (pangearake * (rakemillis - PANGEA_MINRAKE_MILLIS)) / rakemillis;
pangearake -= rake;
}
else rake = 0;
*hostrakep = rake;
*pangearakep = pangearake;
printf("\nP%d: rakemillis.%d total %.8f split %.8f rake %.8f pangearake %.8f\n",player,rakemillis,dstr(total),dstr(split),dstr(rake),dstr(pangearake));
return(split);
}
int32_t pangea_sidepots(struct supernet_info *myinfo,struct table_info *tp,int32_t dispflag,int64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],int64_t *bets)
{
int32_t i,j,nonz,N,n = 0; uint64_t bet,minbet = 0;
memset(sidepots,0,sizeof(uint64_t)*CARDS777_MAXPLAYERS*CARDS777_MAXPLAYERS);
N = tp->G.numactive;
for (j=0; j<N; j++)
sidepots[0][j] = bets[j];
nonz = 1;
while ( nonz > 0 )
{
for (minbet=j=0; j<N; j++)
{
if ( (bet= sidepots[n][j]) != 0 )
{
if ( tp->active[j] != 0 && tp->active[j]->betstatus != CARDS777_FOLD )
{
if ( minbet == 0 || bet < minbet )
minbet = bet;
}
}
}
for (j=nonz=0; j<N; j++)
{
if ( sidepots[n][j] > minbet && tp->active[j] != 0 && tp->active[j]->betstatus != CARDS777_FOLD )
nonz++;
}
if ( nonz > 0 )
{
for (j=0; j<N; j++)
{
if ( sidepots[n][j] > minbet )
{
sidepots[n+1][j] = (sidepots[n][j] - minbet);
sidepots[n][j] = minbet;
}
}
}
if ( ++n >= N )
break;
}
if ( dispflag != 0 )
{
for (i=0; i<n; i++)
{
for (j=0; j<N; j++)
printf("%.8f ",dstr(sidepots[i][j]));
printf("sidepot.%d of %d\n",i,n);
}
}
return(n);
}
int64_t pangea_splitpot(struct supernet_info *myinfo,struct table_info *tp,uint64_t *pangearakep,int64_t sidepot[CARDS777_MAXPLAYERS],int32_t rakemillis)
{
struct player_info *winners[CARDS777_MAXPLAYERS];
int32_t j,n,N,numwinners = 0; uint32_t bestrank,rank; uint8_t tmp; struct player_info *p;
uint64_t total = 0,bet,split,maxrake,rake=0,pangearake=0; char handstr[128],besthandstr[128];
N = tp->G.numactive;
bestrank = 0;
besthandstr[0] = 0;
for (j=n=0; j<N; j++)
{
if ( (bet= sidepot[j]) != 0 )
{
total += bet;
if ( (p= tp->active[j]) != 0 && p->betstatus != CARDS777_FOLD )
{
if ( p->handrank > bestrank )
{
bestrank = p->handrank;
set_handstr(besthandstr,p->hand,0);
//printf("set besthandstr.(%s)\n",besthandstr);
}
}
}
}
for (j=0; j<N; j++)
{
if ( (p= tp->active[j]) != 0 && p->betstatus != CARDS777_FOLD && sidepot[j] > 0 )
{
if ( p->handrank == bestrank )
winners[numwinners++] = p;
rank = set_handstr(handstr,p->hand,0);
if ( handstr[strlen(handstr)-1] == ' ' )
handstr[strlen(handstr)-1] = 0;
//if ( hn->server->H.slot == 0 )
printf("(p%d %14s)",j,handstr[0]!=' '?handstr:handstr+1);
//printf("(%2d %2d).%d ",dp->hands[j][5],dp->hands[j][6],(int32_t)dp->balances[j]);
}
}
if ( numwinners == 0 )
printf("pangea_splitpot error: numwinners.0\n");
else
{
uint64_t maxrakes[CARDS777_MAXPLAYERS+1] = { 0, 0, 1, 2, 2, 3, 3, 3, 3, 3 }; // 2players 1BB, 3-4players, 2BB, 5+players 3BB
for (j=n=0; j<N; j++)
if ( (p= tp->active[j]) != 0 && p->bets > 0 )
n++;
if ( (maxrake= maxrakes[n] * tp->G.bigblind) > tp->G.maxrake )
{
maxrake = tp->G.maxrake;
//if ( strcmp(dp->coinstr,"BTC") == 0 && maxrake < PANGEA_BTCMAXRAKE )
// maxrake = PANGEA_BTCMAXRAKE;
//else if ( maxrake < PANGEA_MAXRAKE )
maxrake = PANGEA_MAXRAKE;
}
split = pangea_winnings(tp->priv.myind,&pangearake,&rake,total,numwinners,rakemillis,maxrake);
(*pangearakep) += pangearake;
for (j=0; j<numwinners; j++)
{
tmp = winners[j]->ind;
pangea_summaryadd(myinfo,tp,CARDS777_WINNINGS,&tmp,sizeof(tmp),(void *)&split,sizeof(split));
winners[j]->balance += split;
winners[j]->won += split;
}
if ( split*numwinners + rake + pangearake != total )
printf("pangea_split total error %.8f != split %.8f numwinners %d rake %.8f pangearake %.8f\n",dstr(total),dstr(split),numwinners,dstr(rake),dstr(pangearake));
//if ( hn->server->H.slot == 0 )
{
printf(" total %.8f split %.8f rake %.8f Prake %.8f hand.(%s) N%d winners ",dstr(total),dstr(split),dstr(rake),dstr(pangearake),besthandstr,tp->numhands);
for (j=0; j<numwinners; j++)
printf("%d ",winners[j]->ind);
printf("\n");
}
}
return(rake);
}
/*char *pangea_input(uint64_t my64bits,uint64_t tableid,cJSON *json)
{
char *actionstr; uint64_t sum,amount=0; int32_t action=0,num,threadid; struct table_info *sp; struct cards777_pubdata *dp; char hex[4096];
threadid = juint(json,"threadid");
if ( (sp= pangea_threadtables(&num,threadid,tableid)) == 0 )
return(clonestr("{\"error\":\"you are not playing on any tables\"}"));
if ( 0 && num != 1 )
return(clonestr("{\"error\":\"more than one active table\"}"));
else if ( (dp= sp->dp) == 0 )
return(clonestr("{\"error\":\"no pubdata ptr for table\"}"));
else if ( dp->hand.undergun != pangea_ind(sp,sp->myslot) || dp->hand.betsize == 0 )
{
printf("undergun.%d threadid.%d myind.%d\n",dp->hand.undergun,sp->tp->threadid,pangea_ind(sp,sp->myslot));
return(clonestr("{\"error\":\"not your turn\"}"));
}
else if ( (actionstr= jstr(json,"action")) == 0 )
return(clonestr("{\"error\":\"on action specified\"}"));
else
{
if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 || strcmp(actionstr,"bet") == 0 || strcmp(actionstr,"raise") == 0 || strcmp(actionstr,"allin") == 0 || strcmp(actionstr,"fold") == 0 )
{
sum = dp->hand.bets[pangea_ind(sp,sp->myslot)];
if ( strcmp(actionstr,"allin") == 0 )
amount = sp->balances[sp->myslot], action = CARDS777_ALLIN;
else if ( strcmp(actionstr,"bet") == 0 )
amount = j64bits(json,"amount"), action = 1;
else
{
if ( dp->hand.betsize == sum )
{
if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 )
action = 0;
else if ( strcmp(actionstr,"raise") == 0 )
{
action = 1;
if ( (amount= dp->hand.lastraise) < j64bits(json,"amount") )
amount = j64bits(json,"amount");
}
else printf("unsupported userinput command.(%s)\n",actionstr);
}
else
{
if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 )
action = 1, amount = (dp->hand.betsize - sum);
else if ( strcmp(actionstr,"raise") == 0 )
{
action = 2;
amount = (dp->hand.betsize - sum);
if ( amount < dp->hand.lastraise )
amount = dp->hand.lastraise;
if ( j64bits(json,"amount") > amount )
amount = j64bits(json,"amount");
}
else if ( strcmp(actionstr,"fold") == 0 )
action = 0;
else printf("unsupported userinput command.(%s)\n",actionstr);
}
}
if ( amount > sp->balances[sp->myslot] )
amount = sp->balances[sp->myslot], action = CARDS777_ALLIN;
pangea_sendcmd(hex,&sp->tp->hn,"action",-1,(void *)&amount,sizeof(amount),dp->hand.cardi,action);
printf("ACTION.(%s)\n",hex);
return(clonestr("{\"result\":\"action submitted\"}"));
}
else return(clonestr("{\"error\":\"illegal action specified, must be: check, call, bet, raise, fold or allin\"}"));
}
}*/