/****************************************************************************** * 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" int64_t pangea_chipsvalue(struct supernet_info *myinfo,struct table_info *tp,int32_t numchips) { return((tp->G.bigblind >> 1) * numchips); } void pangea_playerfold(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_playerbet(struct supernet_info *myinfo,int64_t *actualbetp,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 ( bet == 0 ) // autobet { if ( action == CARDS777_CALL ) bet = hand->betsize; else if ( action == CARDS777_BET ) bet = hand->betsize + hand->lastraise; else if ( action == CARDS777_RAISE ) bet = hand->betsize + hand->lastraise * 2; bet -= player->bets; } *actualbetp = 0; 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); else if ( action == CARDS777_ALLIN ) bet = player->balance; 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_playerfold(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)); *actualbetp = bet; 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; int64_t actualbet; N = tp->G.numactive; for (i=0; iG.N; i++) { tp->G.P[i].ind = i; if ( (tp->snapshot[i]= tp->G.P[i].balance) <= 0 ) pangea_playerfold(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; iactive[i]) != 0 ) { if ( p->balance < tp->G.ante ) pangea_playerfold(myinfo,tp,p); else pangea_playerbet(myinfo,&actualbet,tp,p,tp->G.ante,CARDS777_ANTE); } else printf("unexpected null player ptr\n"); } } for (i=n=0; iG.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_playerfold(myinfo,tp,p); else n++; } if ( n < 2 ) printf("pangea_antes not enough players n.%d\n",n); else { pangea_playerbet(myinfo,&actualbet,tp,tp->active[0],(tp->G.bigblind>>1),CARDS777_SMALLBLIND); pangea_playerbet(myinfo,&actualbet,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; ibalances[i])); if ( bets[i] != 0 ) break; } if ( i == N && hand->checkprod.txid != 0 ) { for (i=0; i 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 0 ) { for (minbet=j=0; jactive[j] != 0 && tp->active[j]->betstatus != CARDS777_FOLD ) { if ( minbet == 0 || bet < minbet ) minbet = bet; } } } for (j=nonz=0; j minbet && tp->active[j] != 0 && tp->active[j]->betstatus != CARDS777_FOLD ) nonz++; } if ( nonz > 0 ) { for (j=0; j minbet ) { sidepots[n+1][j] = (sidepots[n][j] - minbet); sidepots[n][j] = minbet; } } } if ( ++n >= N ) break; } if ( dispflag != 0 ) { for (i=0; iG.numactive; bestrank = 0; besthandstr[0] = 0; for (j=n=0; jactive[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; jactive[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; jactive[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; jind; 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; jind); 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\"}")); } }*/