jl777
9 years ago
64 changed files with 5877 additions and 227 deletions
@ -0,0 +1,526 @@ |
|||
/******************************************************************************
|
|||
* 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" |
|||
|
|||
bits256 cards777_initcrypt(bits256 data,bits256 privkey,bits256 pubkey,int32_t invert) |
|||
{ |
|||
bits256 hash; |
|||
hash = curve25519_shared(privkey,pubkey); |
|||
if ( invert != 0 ) |
|||
hash = crecip_donna(hash); |
|||
return(fmul_donna(data,hash)); |
|||
} |
|||
|
|||
bits256 cards777_cardpriv(bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 cipher) |
|||
{ |
|||
bits256 cardpriv,checkpub; int32_t i; |
|||
for (i=0; i<numcards; i++) |
|||
{ |
|||
cardpriv = cards777_initcrypt(cipher,playerpriv,cardpubs[i],1); |
|||
//printf("(%llx %llx) ",(long long)cardpriv.txid,(long long)curve25519_shared(playerpriv,cardpubs[i]).txid);
|
|||
checkpub = curve25519(cardpriv,curve25519_basepoint9()); |
|||
if ( memcmp(checkpub.bytes,cardpubs[i].bytes,sizeof(bits256)) == 0 ) |
|||
{ |
|||
//printf("%d ",cardpriv.bytes[1]);
|
|||
//printf("decrypted card.%d %llx\n",cardpriv.bytes[1],(long long)cardpriv.txid);
|
|||
return(cardpriv); |
|||
} |
|||
} |
|||
//printf("\nplayerpriv %llx cipher.%llx\n",(long long)playerpriv.txid,(long long)cipher.txid);
|
|||
memset(cardpriv.bytes,0,sizeof(cardpriv)); |
|||
return(cardpriv); |
|||
} |
|||
|
|||
int32_t cards777_checkcard(bits256 *cardprivp,int32_t cardi,int32_t slot,int32_t destplayer,bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 card) |
|||
{ |
|||
bits256 cardpriv; |
|||
cardpriv = cards777_cardpriv(playerpriv,cardpubs,numcards,card); |
|||
if ( cardpriv.txid != 0 ) |
|||
{ |
|||
if ( slot >= 0 && destplayer != slot ) |
|||
printf(">>>>>>>>>>>> ERROR "); |
|||
if ( Debuglevel > 2 ) |
|||
printf("slot.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d]\n",slot,cardi,destplayer,cardpriv.bytes[1]); |
|||
*cardprivp = cardpriv; |
|||
return(cardpriv.bytes[1]); |
|||
} |
|||
memset(cardprivp,0,sizeof(*cardprivp)); |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub) |
|||
{ |
|||
int32_t i; bits256 val,checkcard,ver; |
|||
val = final; |
|||
for (i=numplayers-1; i>0; i--) |
|||
{ |
|||
val = fmul_donna(audit[i],val); |
|||
//if ( memcmp(tmp.bytes,audit[i-1].bytes,sizeof(tmp)) != 0 )
|
|||
// printf("cards777_validate: mismatched audit[%d] %llx vs %llx %llx\n",i-1,(long long)tmp.txid,(long long)audit[i-1].txid,(long long)audit[i].txid);
|
|||
} |
|||
checkcard = val;//fcontract(val);
|
|||
if ( memcmp(checkcard.bytes,audit[0].bytes,sizeof(checkcard)) != 0 ) |
|||
{ |
|||
printf("cards777_validate: checkcard not validated %llx vs %llx numplayers.%d\n",(long long)checkcard.txid,(long long)audit[0].txid,numplayers); |
|||
return(-1); |
|||
} |
|||
ver = cards777_initcrypt(cardpriv,cardpriv,playerpub,0); |
|||
if ( memcmp(checkcard.bytes,ver.bytes,sizeof(checkcard)) != 0 ) |
|||
{ |
|||
printf("cards777_validate: ver not validated %llx vs %llx\n",(long long)checkcard.txid,(long long)ver.txid); |
|||
return(-1); |
|||
} |
|||
return(cardpriv.bytes[1]); |
|||
} |
|||
|
|||
int32_t cards777_shuffle(bits256 *shuffled,bits256 *cards,int32_t numcards,int32_t N) |
|||
{ |
|||
int32_t i,j,pos,nonz,permi[CARDS777_MAXCARDS],desti[CARDS777_MAXCARDS]; uint8_t x; uint64_t mask; |
|||
memset(desti,0,sizeof(desti)); |
|||
for (i=0; i<numcards; i++) |
|||
desti[i] = i; |
|||
for (i=0; i<numcards; i++) |
|||
{ |
|||
OS_randombytes(&x,1); |
|||
pos = (x % ((numcards-1-i) + 1)); |
|||
//printf("%d ",pos);
|
|||
permi[i] = desti[pos]; |
|||
desti[pos] = desti[numcards-1 - i]; |
|||
desti[numcards-1 - i] = -1; |
|||
} |
|||
//printf("pos\n");
|
|||
for (mask=i=nonz=0; i<numcards; i++) |
|||
{ |
|||
if ( 0 && Debuglevel > 2 ) |
|||
printf("%d ",permi[i]); |
|||
mask |= (1LL << permi[i]); |
|||
for (j=0; j<N; j++,nonz++) |
|||
shuffled[nonz] = cards[permi[i]*N + j];//, printf("%llx ",(long long)shuffled[nonz].txid);
|
|||
} |
|||
if ( Debuglevel > 2 ) |
|||
printf("shuffled mask.%llx err.%llx\n",(long long)mask,(long long)(mask ^ ((1LL<<numcards)-1))); |
|||
return(0); |
|||
} |
|||
|
|||
void cards777_layer(bits256 *layered,bits256 *xoverz,bits256 *incards,int32_t numcards,int32_t N) |
|||
{ |
|||
int32_t i,k,nonz = 0; bits256 z_x; |
|||
for (i=nonz=0; i<numcards; i++) |
|||
{ |
|||
for (k=0; k<N; k++,nonz++) |
|||
{ |
|||
xoverz[nonz] = xoverz_donna(rand256(1)); |
|||
z_x = crecip_donna(xoverz[nonz]); |
|||
layered[nonz] = fmul_donna(z_x,incards[nonz]); |
|||
//printf("{%llx -> %llx}.%d ",(long long)incards[nonz].txid,(long long)layered[nonz].txid,nonz);
|
|||
} |
|||
//printf("card.%d\n",i);
|
|||
} |
|||
} |
|||
|
|||
int32_t cards777_calcmofn(uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *xoverz,int32_t numcards,int32_t N) |
|||
{ |
|||
int32_t size,j; |
|||
size = N * sizeof(bits256) * numcards; |
|||
calc_shares(allshares,(void *)xoverz,size,size,M,N,sharenrs); // PM &allshares[playerj * size] to playerJ
|
|||
for (j=0; j<N; j++) |
|||
myshares[j] = &allshares[j * size]; |
|||
return(size); |
|||
} |
|||
|
|||
uint8_t *cards777_recover(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t numcards,int32_t N) |
|||
{ |
|||
void *G; int32_t i,size; uint8_t *recover,recovernrs[255]; |
|||
size = N * sizeof(bits256) * numcards; |
|||
if ( (recover= calloc(1,size)) == 0 ) |
|||
{ |
|||
printf("cards777_recover: unexpected out of memory error\n"); |
|||
return(0); |
|||
} |
|||
memset(recovernrs,0,sizeof(recovernrs)); |
|||
for (i=0; i<N; i++) |
|||
if ( shares[i] != 0 ) |
|||
recovernrs[i] = sharenrs[i]; |
|||
G = gfshare_ctx_init_dec(recovernrs,N,size); |
|||
for (i=0; i<N; i++) |
|||
if ( shares[i] != 0 ) |
|||
gfshare_ctx_dec_giveshare(G,i,shares[i]); |
|||
gfshare_ctx_dec_newshares(G,recovernrs); |
|||
gfshare_ctx_dec_extract(G,recover); |
|||
gfshare_ctx_free(G); |
|||
return(recover); |
|||
} |
|||
|
|||
bits256 cards777_pubkeys(bits256 *pubkeys,int32_t numcards,bits256 cmppubkey) |
|||
{ |
|||
int32_t i; bits256 bp,pubkey,hash,check,prod; |
|||
memset(check.bytes,0,sizeof(check)); |
|||
memset(bp.bytes,0,sizeof(bp)), bp.bytes[0] = 9; |
|||
prod = fmul_donna(bp,crecip_donna(bp)); |
|||
for (i=0; i<numcards; i++) |
|||
{ |
|||
pubkey = pubkeys[i]; |
|||
vcalc_sha256(0,hash.bytes,pubkey.bytes,sizeof(pubkey)); |
|||
hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; |
|||
prod = fmul_donna(prod,hash); |
|||
} |
|||
check = prod; |
|||
if ( cmppubkey.txid != 0 ) |
|||
{ |
|||
if ( memcmp(check.bytes,cmppubkey.bytes,sizeof(check)) != 0 ) |
|||
printf("cards777_pubkeys: mismatched pubkeys permicheck.%llx != prod.%llx\n",(long long)check.txid,(long long)pubkey.txid); |
|||
//else printf("pubkeys matched\n");
|
|||
} |
|||
return(check); |
|||
} |
|||
|
|||
bits256 cards777_initdeck(bits256 *cards,bits256 *cardpubs,int32_t numcards,int32_t N,bits256 *playerpubs,bits256 *playerprivs) |
|||
{ |
|||
char buf[4096]; bits256 privkey,pubkey,hash, bp,prod; int32_t i,j,nonz,num = 0; uint64_t mask = 0; |
|||
bp = curve25519_basepoint9(); |
|||
prod = crecip_donna(bp); |
|||
prod = fmul_donna(bp,prod); |
|||
if ( Debuglevel > 2 ) |
|||
printf("card777_initdeck unit.%llx\n",(long long)prod.txid); |
|||
nonz = 0; |
|||
while ( mask != (1LL << numcards)-1 ) |
|||
{ |
|||
privkey = curve25519_keypair(&pubkey); |
|||
buf[0] = 0; |
|||
if ( (i=privkey.bytes[1]) < numcards && ((1LL << i) & mask) == 0 ) |
|||
{ |
|||
mask |= (1LL << i); |
|||
cardpubs[num] = pubkey; |
|||
if ( playerprivs != 0 ) |
|||
sprintf(buf+strlen(buf),"%llx.",(long long)privkey.txid); |
|||
for (j=0; j<N; j++,nonz++) |
|||
{ |
|||
cards[nonz] = cards777_initcrypt(privkey,privkey,playerpubs[j],0); |
|||
if ( playerprivs != 0 ) |
|||
sprintf(buf+strlen(buf),"[%llx * %llx -> %llx] ",(long long)cards[nonz].txid,(long long)curve25519_shared(playerprivs[j],pubkey).txid,(long long)cards777_initcrypt(cards[nonz],playerprivs[j],pubkey,1).txid); |
|||
} |
|||
vcalc_sha256(0,hash.bytes,pubkey.bytes,sizeof(pubkey)); |
|||
hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; |
|||
prod = fmul_donna(prod,hash); |
|||
//printf("(%s) num.%d [%llx] %d prod.%llx\n",buf,num,(long long)mask ^ ((1LL << numcards)-1),i,(long long)prod.txid);
|
|||
num++; |
|||
} |
|||
} |
|||
if ( playerprivs != 0 ) |
|||
printf("\n%llx %llx playerprivs\n",(long long)playerprivs[0].txid,(long long)playerprivs[1].txid); |
|||
if ( 0 && Debuglevel > 2 ) |
|||
{ |
|||
for (i=0; i<numcards; i++) |
|||
printf("%d ",cards[i*N].bytes[1]); |
|||
printf("init order %llx (%llx %llx)\n",(long long)prod.txid,(long long)playerpubs[0].txid,(long long)playerpubs[1].txid); |
|||
} |
|||
return(prod); |
|||
} |
|||
|
|||
uint8_t *cards777_encode(bits256 *encoded,bits256 *xoverz,uint8_t *allshares,uint8_t *myshares[],uint8_t sharenrs[255],int32_t M,bits256 *ciphers,int32_t numcards,int32_t N) |
|||
{ |
|||
bits256 shuffled[CARDS777_MAXCARDS * CARDS777_MAXPLAYERS]; |
|||
cards777_shuffle(shuffled,ciphers,numcards,N); |
|||
cards777_layer(encoded,xoverz,shuffled,numcards,N); |
|||
memset(sharenrs,0,255); |
|||
init_sharenrs(sharenrs,0,N,N); |
|||
cards777_calcmofn(allshares,myshares,sharenrs,M,xoverz,numcards,N); |
|||
memcpy(ciphers,shuffled,numcards * N * sizeof(bits256)); |
|||
if ( 1 ) |
|||
{ |
|||
/*{
|
|||
init_hexbytes_noT(nrs,dp->hand.sharenrs,dp->N); |
|||
if ( (nrs= jstr(json,"sharenrs")) != 0 ) |
|||
decode_hex(dp->hand.sharenrs,(int32_t)strlen(nrs)>>1,nrs); |
|||
}*/ |
|||
int32_t i,j,m,size; uint8_t *recover,*testshares[CARDS777_MAXPLAYERS],testnrs[255]; |
|||
size = N * sizeof(bits256) * numcards; |
|||
for (j=0; j<1; j++) |
|||
{ |
|||
memset(testnrs,0,sizeof(testnrs)); |
|||
memset(testshares,0,sizeof(testshares)); |
|||
m = (rand() % N) + 1; |
|||
if ( m < M ) |
|||
m = M; |
|||
if ( init_sharenrs(testnrs,sharenrs,m,N) < 0 ) |
|||
{ |
|||
printf("iter.%d error init_sharenrs(m.%d of n.%d)\n",j,m,N); |
|||
return(0); |
|||
} |
|||
for (i=0; i<N; i++) |
|||
if ( testnrs[i] == sharenrs[i] ) |
|||
testshares[i] = myshares[i]; |
|||
if ( (recover= cards777_recover(testshares,sharenrs,M,numcards,N)) != 0 ) |
|||
{ |
|||
if ( memcmp(xoverz,recover,size) != 0 ) |
|||
fprintf(stderr,"(ERROR m.%d M.%d N.%d)\n",m,M,N); |
|||
else fprintf(stderr,"reconstructed with m.%d M.%d N.%d\n",m,M,N); |
|||
free(recover); |
|||
} else printf("nullptr from cards777_recover\n"); |
|||
} |
|||
} |
|||
return(allshares); |
|||
} |
|||
|
|||
bits256 cards777_decode(bits256 *seedp,bits256 *xoverz,int32_t destplayer,bits256 cipher,bits256 *outcards,int32_t numcards,int32_t N) |
|||
{ |
|||
int32_t i,ind; |
|||
memset(seedp->bytes,0,sizeof(*seedp)); |
|||
for (i=0; i<numcards; i++) |
|||
{ |
|||
ind = i*N + destplayer; |
|||
//printf("[%llx] ",(long long)outcards[ind].txid);
|
|||
if ( memcmp(outcards[ind].bytes,cipher.bytes,32) == 0 ) |
|||
{ |
|||
*seedp = xoverz[ind]; |
|||
cipher = fmul_donna(xoverz[ind],cipher); |
|||
//printf("matched %d -> %llx\n",i,(long long)cipher.txid);
|
|||
return(cipher); |
|||
} |
|||
} |
|||
if ( i == numcards ) |
|||
{ |
|||
printf("decryption error %llx: destplayer.%d no match\n",(long long)cipher.txid,destplayer); |
|||
memset(cipher.bytes,0,sizeof(cipher)); |
|||
//cipher = cards777_cardpriv(playerpriv,cardpubs,numcards,cipher);
|
|||
} |
|||
return(cipher); |
|||
} |
|||
|
|||
struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N) |
|||
{ |
|||
struct cards777_privdata *priv; |
|||
if ( (priv= calloc(1,sizeof(*priv) + sizeof(bits256) * (2*((N * numcards * N) + (N * numcards))))) == 0 ) |
|||
{ |
|||
printf("cards777_allocpriv: unexpected out of memory error\n"); |
|||
return(0); |
|||
} |
|||
priv->audits = &priv->data[0]; |
|||
priv->outcards = &priv->audits[N * numcards * N]; |
|||
priv->xoverz = &priv->outcards[N * numcards]; |
|||
priv->allshares = (void *)&priv->xoverz[N * numcards]; // N*numcards*N
|
|||
return(priv); |
|||
} |
|||
|
|||
struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N) |
|||
{ |
|||
struct cards777_pubdata *dp; |
|||
if ( (dp= calloc(1,sizeof(*dp) + sizeof(bits256) * ((numcards + 1) + (N * numcards)))) == 0 ) |
|||
{ |
|||
printf("cards777_allocpub: unexpected out of memory error\n"); |
|||
return(0); |
|||
} |
|||
dp->M = M, dp->N = N, dp->numcards = numcards; |
|||
dp->hand.cardpubs = &dp->data[0]; |
|||
dp->hand.final = &dp->hand.cardpubs[numcards + 1]; |
|||
return(dp); |
|||
} |
|||
|
|||
#ifdef notyet |
|||
int32_t cards777_testinit(struct hostnet777_server *srv,int32_t M,struct hostnet777_client **clients,int32_t N,int32_t numcards) |
|||
{ |
|||
//static int64_t balances[9];
|
|||
int32_t i; uint8_t sharenrs[255]; //,destplayer,cardibits256 *ciphers,cardpriv,card; uint64_t mask = 0;
|
|||
struct cards777_pubdata *dp; //struct cards777_privdata *priv; struct pangea_info *sp;
|
|||
if ( srv->num != N ) |
|||
{ |
|||
printf("srv->num.%d != N.%d\n",srv->num,N); |
|||
return(-1); |
|||
} |
|||
memset(sharenrs,0,sizeof(sharenrs)); |
|||
init_sharenrs(sharenrs,0,N,N); // this needs to be done to start a hand
|
|||
for (i=0; i<N; i++) |
|||
{ |
|||
dp = srv->clients[i].pubdata = cards777_allocpub(M,numcards,N); |
|||
//sp = dp->table;
|
|||
memcpy(dp->hand.sharenrs,sharenrs,dp->N); |
|||
/*for (j=0; j<N; j++)
|
|||
sp->playerpubs[j] = srv->clients[j].pubkey; |
|||
for (j=0; j<N; j++) |
|||
{ |
|||
balances[j] = 100; |
|||
dp->balances[j] = &balances[j]; |
|||
}*/ |
|||
printf("deprecated, need to init sp->\n"); |
|||
//priv = srv->clients[i].privdata = cards777_allocpriv(numcards,N);
|
|||
//priv->privkey = (i == 0) ? srv->H.privkey : clients[i]->H.privkey;
|
|||
/*if ( i == 0 )
|
|||
dp->checkprod = cards777_initdeck(priv->outcards,dp->cardpubs,numcards,N,dp->playerpubs), refdp = dp; |
|||
else memcpy(dp->cardpubs,refdp->cardpubs,sizeof(*dp->cardpubs) * numcards);*/ |
|||
} |
|||
return(0); |
|||
/*priv = srv->clients[0].privdata;
|
|||
ciphers = priv->outcards; |
|||
for (i=1; i<N; i++) |
|||
{ |
|||
dp = srv->clients[i].pubdata; |
|||
priv = srv->clients[i].privdata; |
|||
cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,dp->sharenrs,dp->M,ciphers,dp->numcards,dp->N); |
|||
ciphers = priv->outcards; |
|||
} |
|||
for (cardi=0; cardi<dp->numcards; cardi++) |
|||
{ |
|||
for (destplayer=0; destplayer<dp->N; destplayer++) |
|||
{ |
|||
priv = srv->clients[dp->N - 1].privdata; |
|||
card = priv->outcards[cardi*dp->N + destplayer]; |
|||
for (i=N-1; i>=0; i--) |
|||
{ |
|||
j = (i > 0) ? i : destplayer; |
|||
//printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j);
|
|||
dp = srv->clients[j].pubdata; |
|||
priv = srv->clients[j].privdata; |
|||
cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card); |
|||
if ( cardpriv.txid != 0 ) |
|||
{ |
|||
mask |= (1LL << cardpriv.bytes[1]); |
|||
if ( destplayer != j ) |
|||
printf(">>>>>>>>>>>> ERROR "); |
|||
printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); |
|||
break; |
|||
} |
|||
card = cards777_decode(priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N); |
|||
cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card); |
|||
if ( cardpriv.txid != 0 ) |
|||
{ |
|||
mask |= (1LL << cardpriv.bytes[1]); |
|||
if ( destplayer != j ) |
|||
printf(">>>>>>>>>>>> ERROR "); |
|||
printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
printf("cardi.%d\n\n",cardi); |
|||
}*/ |
|||
return(0); |
|||
} |
|||
|
|||
void cards777_initid(struct hostnet777_id *id,bits256 pubkey,struct cards777_pubdata *dp,struct cards777_privdata *priv) |
|||
{ |
|||
id->pubkey = pubkey; |
|||
id->nxt64bits = acct777_nxt64bits(pubkey); |
|||
id->pubdata = dp; |
|||
id->privdata = priv; |
|||
id->pmsock = -1; |
|||
} |
|||
|
|||
void cards777_test() |
|||
{ |
|||
int32_t i,j,vals[52][52]; bits256 keypairs[52][2],otherpairs[52][2],matrix[52][52]; char buf[512]; |
|||
FILE *fp; |
|||
if ( (fp= fopen("/persistent/test","rb")) != 0 ) |
|||
{ |
|||
if ( fread(buf,6,1,fp) <= 0 ) |
|||
printf("read error for /persistent/test\n"); |
|||
buf[6] = 0; |
|||
printf("test exists (%s)\n",buf); |
|||
fclose(fp); |
|||
} else printf("testfile not present\n"); |
|||
for (i=0; i<52; i++) |
|||
keypairs[i][0] = curve25519_keypair(&keypairs[i][1]); |
|||
for (j=0; j<52; j++) |
|||
otherpairs[j][0] = curve25519_keypair(&otherpairs[j][1]); |
|||
bits256 zmone;zmone = crecip_donna(keypairs[0][0]); |
|||
printf("DEBUG.%d %llx vs %llx | %llx -> %llx/%llx\n",Debuglevel,(long long)keypairs[0][0].txid,(long long)fcontract(fexpand(keypairs[0][0])).txid,(long long)zmone.txid,(long long)fexpand(fmul_donna(keypairs[0][0],zmone)).txid,(long long)fmul(fexpand(keypairs[0][0]),fexpand(zmone)).txid); |
|||
for (i=0; i<52; i++) |
|||
{break; |
|||
buf[0] = 0; |
|||
for (j=0; j<52; j++) |
|||
{ |
|||
matrix[i][j] = fmul_donna(keypairs[j][1],otherpairs[i][1]); |
|||
vals[i][j] = matrix[i][j].bytes[1] % 52; |
|||
sprintf(buf+strlen(buf),"%d ",vals[i][j]); |
|||
} |
|||
printf("%s\n",buf); |
|||
} |
|||
struct hostnet777_server *srv; int32_t M,N = 9; //struct hostnet777_client **clients;
|
|||
struct cards777_pubdata *dp; struct cards777_privdata *priv; |
|||
bits256 checkprod,cards[52],playerpubs[9],playerprivs[9]; |
|||
//clients = calloc(N+1,sizeof(*clients));
|
|||
if ( (srv= hostnet777_server(keypairs[0][0],keypairs[0][1],0,0,0,N)) == 0 ) |
|||
{ |
|||
printf("cant create hostnet777 server\n"); |
|||
return; |
|||
} |
|||
M = (N >> 1) + 1; |
|||
for (i=0; i<N; i++) |
|||
{ |
|||
cards777_initid(&srv->clients[i],keypairs[i][1],cards777_allocpub(M,52,N),cards777_allocpriv(52,N)); |
|||
playerprivs[i] = keypairs[i][0]; |
|||
playerpubs[i] = keypairs[i][1]; |
|||
if ( i == 0 ) |
|||
{ |
|||
srv->H.privkey = keypairs[i][0]; |
|||
srv->H.pubkey = keypairs[i][1]; |
|||
} |
|||
else |
|||
{ |
|||
} |
|||
} |
|||
dp = srv->clients[0].pubdata; |
|||
dp->N = N; dp->M = M; dp->numcards = 52; |
|||
checkprod = cards777_initdeck(cards,dp->hand.cardpubs,52,N,playerpubs,0); |
|||
printf("deck initialzed %llx\n",(long long)checkprod.txid); |
|||
uint8_t sharenrs[255]; uint64_t mask = 0; int32_t cardi,destplayer; |
|||
bits256 card,cardpriv,seed,*ciphers = cards; |
|||
for (i=1; i<N; i++) |
|||
{ |
|||
dp = srv->clients[i].pubdata; |
|||
dp->N = N; dp->M = M; dp->numcards = 52; |
|||
priv = srv->clients[i].privdata; |
|||
cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,sharenrs,dp->M,ciphers,dp->numcards,dp->N); |
|||
ciphers = priv->outcards; |
|||
} |
|||
printf("deck encrypted\n"); |
|||
for (cardi=0; cardi<dp->numcards; cardi++) |
|||
{ |
|||
for (destplayer=0; destplayer<dp->N; destplayer++) |
|||
{ |
|||
priv = srv->clients[dp->N - 1].privdata; |
|||
card = priv->outcards[cardi*dp->N + destplayer]; |
|||
for (i=N-1; i>=0; i--) |
|||
{ |
|||
j = (i > 0) ? i : destplayer; |
|||
//printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j);
|
|||
dp = srv->clients[j].pubdata; |
|||
priv = srv->clients[j].privdata; |
|||
cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card); |
|||
if ( cardpriv.txid != 0 ) |
|||
{ |
|||
mask |= (1LL << cardpriv.bytes[1]); |
|||
if ( destplayer != j ) |
|||
printf(">>>>>>>>>>>> ERROR "); |
|||
printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); |
|||
break; |
|||
} |
|||
card = cards777_decode(&seed,priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N); |
|||
cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card); |
|||
if ( cardpriv.txid != 0 ) |
|||
{ |
|||
mask |= (1LL << cardpriv.bytes[1]); |
|||
if ( destplayer != j ) |
|||
printf(">>>>>>>>>>>> ERROR "); |
|||
printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
printf("cardi.%d\n\n",cardi); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -1,3 +1,3 @@ |
|||
#iguana_html.c |
|||
|
|||
SOURCES := SuperNET.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c |
|||
SOURCES := SuperNET.c pangea_api.c pangea_fsm.c pangea_network.c pangea_init.c poker.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c |
|||
|
@ -0,0 +1,189 @@ |
|||
/******************************************************************************
|
|||
* 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. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
#ifndef PANGEA777_H |
|||
#define PANGEA777_H |
|||
#include "iguana777.h" |
|||
|
|||
#define TEST_TRANSPORT "http://"
|
|||
|
|||
#define _PANGEA_MAXTHREADS 9 |
|||
#define PANGEA_MINRAKE_MILLIS 5 |
|||
#define PANGEA_USERTIMEOUT 60 |
|||
#define PANGEA_MAX_HOSTRAKE 5 |
|||
#define PANGEA_BTCMAXRAKE (SATOSHIDEN / 100) |
|||
#define PANGEA_MAXRAKE (3 * SATOSHIDEN) |
|||
#define PANGEA_HANDGAP 30 |
|||
#define PANGEA_PAUSE 5 |
|||
|
|||
#define CARDS777_MAXCARDS 52 |
|||
#define CARDS777_MAXPLAYERS 9 |
|||
#define CARDS777_FOLD -1 |
|||
#define CARDS777_START 1 |
|||
#define CARDS777_ANTE 2 |
|||
#define CARDS777_SMALLBLIND 3 |
|||
#define CARDS777_BIGBLIND 4 |
|||
#define CARDS777_CHECK 5 |
|||
#define CARDS777_CALL 6 |
|||
#define CARDS777_BET 7 |
|||
#define CARDS777_RAISE 8 |
|||
#define CARDS777_FULLRAISE 9 |
|||
#define CARDS777_SENTCARDS 10 |
|||
#define CARDS777_ALLIN 11 |
|||
#define CARDS777_FACEUP 12 |
|||
#define CARDS777_WINNINGS 13 |
|||
#define CARDS777_RAKES 14 |
|||
#define CARDS777_CHANGES 15 |
|||
#define CARDS777_SNAPSHOT 16 |
|||
|
|||
struct cards777_handinfo |
|||
{ |
|||
bits256 checkprod,*cardpubs,*final,community256[5],cards[CARDS777_MAXPLAYERS][2]; |
|||
uint64_t othercardpubs[CARDS777_MAXPLAYERS]; |
|||
int64_t havemasks[CARDS777_MAXPLAYERS],betsize,hostrake,pangearake,lastraise,bets[CARDS777_MAXPLAYERS],snapshot[CARDS777_MAXPLAYERS+1],won[CARDS777_MAXPLAYERS]; |
|||
uint32_t starttime,handmask,lastbettor,startdecktime,betstarted,finished,encodestarted; |
|||
uint32_t cardi,userinput_starttime,handranks[CARDS777_MAXPLAYERS]; |
|||
int8_t betstatus[CARDS777_MAXPLAYERS],actions[CARDS777_MAXPLAYERS],turnis[CARDS777_MAXPLAYERS]; |
|||
uint8_t numactions,undergun,community[5],sharenrs[CARDS777_MAXPLAYERS][255],hands[CARDS777_MAXPLAYERS][7]; |
|||
}; |
|||
|
|||
struct cards777_pubdata |
|||
{ |
|||
int64_t snapshot[CARDS777_MAXPLAYERS]; |
|||
uint64_t maxrake,hostrake,bigblind,ante,pangearake,summaries,mismatches; |
|||
uint32_t button,readymask,numhands,rakemillis,minbuyin,maxbuyin,summarysize; |
|||
void *table; struct cards777_handinfo hand; |
|||
char newhand[65536],coinstr[16]; uint8_t M,N,numcards,summary[65536]; bits256 data[]; |
|||
}; |
|||
|
|||
struct cards777_privdata |
|||
{ |
|||
bits256 holecards[2],*audits,*outcards,*xoverz; |
|||
//,*reconstructed[CARDS777_MAXPLAYERS],*mofn[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS];
|
|||
uint8_t *myshares[CARDS777_MAXPLAYERS],*allshares,hole[2],cardis[2],automuck,autofold; |
|||
bits256 data[]; |
|||
}; |
|||
|
|||
extern int32_t Debuglevel; |
|||
bits256 xoverz_donna(bits256 a); |
|||
bits256 crecip_donna(bits256 a); |
|||
bits256 fmul_donna(bits256 a,bits256 b); |
|||
|
|||
void calc_shares(unsigned char *shares,unsigned char *secret,int32_t size,int32_t width,int32_t M,int32_t N,unsigned char *sharenrs); |
|||
int32_t init_sharenrs(unsigned char sharenrs[255],unsigned char *orig,int32_t m,int32_t n); |
|||
|
|||
struct pangea_info |
|||
{ |
|||
uint32_t timestamp,numaddrs,minbuyin,maxbuyin; |
|||
int64_t balances[CARDS777_MAXPLAYERS]; uint8_t isbot[CARDS777_MAXPLAYERS]; bits256 playerpubs[CARDS777_MAXPLAYERS]; |
|||
uint64_t basebits,bigblind,ante,addrs[CARDS777_MAXPLAYERS],active[CARDS777_MAXPLAYERS],tableid; |
|||
char btcpubkeystr[67],wipstr[64],coinstr[16],multisigaddr[64],scriptPubKey[128],redeemScript[4096]; |
|||
uint8_t addrtype,p2shtype,wiftype,btcpub[33]; |
|||
int32_t myslot,myind,numactive,buyinvouts[CARDS777_MAXPLAYERS]; uint64_t buyinamounts[CARDS777_MAXPLAYERS]; |
|||
char buyintxids[CARDS777_MAXPLAYERS][128],coinaddrs[CARDS777_MAXPLAYERS][67],btcpubkeys[CARDS777_MAXPLAYERS][67]; |
|||
struct pangea_thread *tp; struct cards777_privdata *priv; struct cards777_pubdata *dp; |
|||
} *TABLES[100]; |
|||
|
|||
//./BitcoinDarkd SuperNET '{"agent":"InstantDEX","method":"orderbook","exchange":"active","base":"NXT","rel":"BTC"}'
|
|||
// ./SNapi "{\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"exchange\":\"pangea\",\"base\":\"NXT\"}"
|
|||
|
|||
// ./SNapi "{\"agent\":\"InstantDEX\",\"method\":\"placebid\",\"exchange\":\"pangea\",\"base\":\"NXT\"}"
|
|||
|
|||
struct pangeanet777_endpoint { char endpoint[128],transport[16],ipaddr[64]; uint16_t port; }; |
|||
struct pangeanet777_id { bits256 pubkey; uint64_t nxt64bits; void *privdata,*pubdata; int32_t pmsock; uint32_t lastcontact; }; |
|||
union pangeanet777 { struct pangeanet777_server *server; struct pangeanet777_client *client; }; |
|||
struct pangeanet777_hdr |
|||
{ |
|||
queue_t Q; bits256 privkey,pubkey; |
|||
void *privdata,*pubdata; uint64_t nxt64bits;//,recvhashes[64];
|
|||
void (*pollfunc)(union pangeanet777 *hn); |
|||
uint32_t lastping; int32_t slot,done,state,ind; |
|||
}; |
|||
|
|||
struct pangeanet777_client { struct pangeanet777_hdr H; int32_t subsock; struct pangeanet777_id my; uint64_t balance,tableid; }; |
|||
|
|||
struct pangeanet777_server |
|||
{ |
|||
struct pangeanet777_hdr H; |
|||
int32_t num,max,pubsock; struct pangeanet777_endpoint ep; //queue_t mailboxQ[CARDS777_MAXPLAYERS];
|
|||
struct pangeanet777_id clients[]; |
|||
}; |
|||
|
|||
struct pangea_thread |
|||
{ |
|||
union pangeanet777 hn; uint64_t nxt64bits; int32_t threadid,ishost,M,N,numcards; |
|||
} *THREADS[_PANGEA_MAXTHREADS]; |
|||
|
|||
int32_t SuperNET_copybits(int32_t reverse,uint8_t *dest,uint8_t *src,int32_t len); |
|||
|
|||
int32_t cardstr(char *cardstr,uint8_t card); |
|||
uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose); |
|||
|
|||
struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N); |
|||
struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N); |
|||
bits256 cards777_initdeck(bits256 *cards,bits256 *cardpubs,int32_t numcards,int32_t N,bits256 *playerpubs,bits256 *playerprivs); |
|||
bits256 cards777_pubkeys(bits256 *pubkeys,int32_t numcards,bits256 cmppubkey); |
|||
int32_t cards777_checkcard(bits256 *cardprivp,int32_t cardi,int32_t slot,int32_t destplayer,bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 card); |
|||
int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub); |
|||
bits256 cards777_decode(bits256 *seedp,bits256 *xoverz,int32_t destplayer,bits256 cipher,bits256 *outcards,int32_t numcards,int32_t N); |
|||
uint8_t *cards777_encode(bits256 *encoded,bits256 *xoverz,uint8_t *allshares,uint8_t *myshares[],uint8_t sharenrs[255],int32_t M,bits256 *ciphers,int32_t numcards,int32_t N); |
|||
|
|||
int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits); |
|||
int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits); |
|||
struct pangea_info *pangea_find64(uint64_t tableid,uint64_t nxt64bits); |
|||
struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid); |
|||
int32_t pangea_neworder(struct cards777_pubdata *dp,struct pangea_info *sp,uint64_t *active,int32_t numactive); |
|||
|
|||
cJSON *pangea_tablestatus(struct pangea_info *sp); |
|||
void pangea_summary(union pangeanet777 *hn,struct cards777_pubdata *dp,uint8_t type,void *arg0,int32_t size0,void *arg1,int32_t size1); |
|||
void pangea_startbets(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t cardi); |
|||
void pangea_checkantes(union pangeanet777 *hn,struct cards777_pubdata *dp); |
|||
uint64_t pangea_bot(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t turni,int32_t cardi,uint64_t betsize); |
|||
char *pangea_dispsummary(struct pangea_info *sp,int32_t verbose,uint8_t *summary,int32_t summarysize,uint64_t tableid,int32_t handid,int32_t numplayers); |
|||
char *_pangea_input(uint64_t my64bits,uint64_t tableid,cJSON *json); |
|||
void pangea_finish(union pangeanet777 *hn,struct cards777_pubdata *dp); |
|||
void pangea_serverstate(union pangeanet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv); |
|||
|
|||
int32_t pangea_anotherhand(void *hn,struct cards777_pubdata *dp,int32_t sleepflag); |
|||
void pangea_clearhand(struct cards777_pubdata *dp,struct cards777_handinfo *hand,struct cards777_privdata *priv); |
|||
void pangea_create_newtable(char *retbuf,struct pangea_info *sp,struct cards777_pubdata *dp,uint64_t *isbot); |
|||
void pangea_buyins(uint32_t *minbuyinp,uint32_t *maxbuyinp); |
|||
int32_t pangea_sidepots(int32_t dispflag,uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],struct cards777_pubdata *dp,int64_t *bets); |
|||
int64_t pangea_splitpot(int64_t *won,uint64_t *pangearakep,uint64_t sidepot[CARDS777_MAXPLAYERS],union pangeanet777 *hn,int32_t rakemillis); |
|||
int32_t pangea_actives(int32_t *activej,struct cards777_pubdata *dp); |
|||
int32_t pangea_bet(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player,int64_t bet,int32_t action); |
|||
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); |
|||
int32_t _pangea_addfunds(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind); |
|||
void _pangea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind); |
|||
|
|||
void pangea_sendcmd(char *hex,union pangeanet777 *hn,char *cmdstr,int32_t destplayer,uint8_t *data,int32_t datalen,int32_t cardi,int32_t turni); |
|||
int32_t pangea_slotA(struct pangea_info *sp); |
|||
int32_t pangea_slotB(struct pangea_info *sp); |
|||
int32_t pangea_slot(struct pangea_info *sp,int32_t ind); |
|||
int32_t pangea_ind(struct pangea_info *sp,int32_t slot); |
|||
int32_t pangea_slot(struct pangea_info *sp,int32_t ind); |
|||
int32_t pangea_poll(uint64_t *senderbitsp,uint32_t *timestampp,union pangeanet777 *hn); |
|||
|
|||
int32_t pangeanet777_register(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot); |
|||
struct pangeanet777_client *pangeanet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot); |
|||
struct pangeanet777_server *pangeanet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients); |
|||
int32_t pangeanet777_idle(union pangeanet777 *hn); |
|||
void pangeanet777_msg(uint64_t destbits,bits256 destpub,union pangeanet777 *src,int32_t blindflag,char *jsonstr,int32_t len); |
|||
struct pangea_info *pangea_threadtables(int32_t *nump,int32_t threadid,uint64_t tableid); |
|||
|
|||
extern int32_t Debuglevel,PANGEA_MAXTHREADS,Showmode,Autofold; |
|||
bits256 issue_getpubkey(int32_t *haspubkeyp,char *acct); |
|||
|
|||
#endif |
@ -0,0 +1,594 @@ |
|||
/******************************************************************************
|
|||
* 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_sendcmd(char *hex,union pangeanet777 *hn,char *cmdstr,int32_t destplayer,uint8_t *data,int32_t datalen,int32_t cardi,int32_t turni) |
|||
{ |
|||
int32_t n,hexlen,blindflag = 0; uint64_t destbits; bits256 destpub; cJSON *json; char hoststr[1024]; struct pangea_info *sp; |
|||
struct cards777_pubdata *dp = hn->client->H.pubdata; |
|||
hoststr[0] = 0; |
|||
sp = dp->table; |
|||
sprintf(hex,"{\"cmd\":\"%s\",\"turni\":%d,\"myslot\":%d,\"myind\":%d,\"cardi\":%d,\"dest\":%d,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,%s\"data\":\"",cmdstr,turni,hn->client->H.slot,pangea_ind(dp->table,hn->client->H.slot),cardi,destplayer,(long long)hn->client->H.nxt64bits,(long)time(NULL),datalen,hoststr); |
|||
n = (int32_t)strlen(hex); |
|||
if ( strcmp(cmdstr,"preflop") == 0 ) |
|||
{ |
|||
memcpy(&hex[n],data,datalen+1); |
|||
hexlen = (int32_t)strlen(hex)+1; |
|||
PNACL_message("P%d HEX.[] hexlen.%d n.%d\n",hn->server->H.slot,hexlen,datalen); |
|||
} |
|||
else if ( data != 0 && datalen != 0 ) |
|||
init_hexbytes_noT(&hex[n],data,datalen); |
|||
strcat(hex,"\"}"); |
|||
if ( (json= cJSON_Parse(hex)) == 0 ) |
|||
{ |
|||
PNACL_message("error creating json\n"); |
|||
return; |
|||
} |
|||
free_json(json); |
|||
hexlen = (int32_t)strlen(hex)+1; |
|||
//PNACL_message("HEX.[%s] hexlen.%d n.%d\n",hex,hexlen,datalen);
|
|||
if ( destplayer < 0 )//|| ((1LL << destplayer) & dp->pmworks) == 0 )
|
|||
{ |
|||
destbits = 0; |
|||
memset(destpub.bytes,0,sizeof(destpub)); |
|||
//PNACL_message("T%d broadcasts %d\n",hn->client->H.slot,hexlen);
|
|||
} |
|||
else |
|||
{ |
|||
destpub = sp->playerpubs[pangea_slot(sp,destplayer)]; |
|||
destbits = acct777_nxt64bits(destpub); |
|||
//PNACL_message("T%d sends %d to dest.%d\n",hn->client->H.slot,hexlen,destplayer);
|
|||
} |
|||
pangeanet777_msg(destbits,destpub,hn,blindflag,hex,hexlen); |
|||
} |
|||
|
|||
char *_pangea_status(uint64_t my64bits,uint64_t tableid,cJSON *json) |
|||
{ |
|||
int32_t i,j,threadid = juint(json,"threadid"); struct pangea_info *sp; cJSON *item,*array=0,*retjson = 0; |
|||
if ( tableid != 0 ) |
|||
{ |
|||
if ( (sp= pangea_find(tableid,threadid)) != 0 ) |
|||
{ |
|||
if ( (item= pangea_tablestatus(sp)) != 0 ) |
|||
{ |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"result","success"); |
|||
jadd(retjson,"table",item); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
{ |
|||
if ( (sp= TABLES[i]) != 0 ) |
|||
{ |
|||
for (j=0; j<sp->numaddrs; j++) |
|||
if ( sp->addrs[j] == my64bits ) |
|||
{ |
|||
if ( (item= pangea_tablestatus(sp)) != 0 ) |
|||
{ |
|||
if ( array == 0 ) |
|||
array = cJSON_CreateArray(); |
|||
jaddi(array,item); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
retjson = cJSON_CreateObject(); |
|||
if ( array == 0 ) |
|||
jaddstr(retjson,"error","no table status"); |
|||
else |
|||
{ |
|||
jaddstr(retjson,"result","success"); |
|||
jadd(retjson,"tables",array); |
|||
} |
|||
jadd64bits(retjson,"nxtaddr",my64bits); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
/*int32_t pangea_idle(struct supernet_info *plugin)
|
|||
{ |
|||
int32_t i,n,m,pinggap = 1; uint64_t senderbits; uint32_t timestamp; struct pangea_thread *tp; union pangeanet777 *hn; |
|||
struct cards777_pubdata *dp; char hex[1024]; |
|||
while ( 1 ) |
|||
{ |
|||
for (i=n=m=0; i<_PANGEA_MAXTHREADS; i++) |
|||
{ |
|||
if ( (tp= THREADS[i]) != 0 ) |
|||
{ |
|||
hn = &tp->hn; |
|||
//PNACL_message("pangea idle player.%d\n",hn->client->H.slot);
|
|||
if ( hn->client->H.done == 0 ) |
|||
{ |
|||
n++; |
|||
if ( pangeanet777_idle(hn) != 0 ) |
|||
m++; |
|||
pangea_poll(&senderbits,×tamp,hn); |
|||
dp = hn->client->H.pubdata; |
|||
if ( dp != 0 && hn->client->H.slot == pangea_slotA(dp->table) ) |
|||
pinggap = 1; |
|||
if ( hn->client != 0 && dp != 0 ) |
|||
{ |
|||
if ( time(NULL) > hn->client->H.lastping + pinggap ) |
|||
{ |
|||
if ( 0 && (dp= hn->client->H.pubdata) != 0 ) |
|||
{ |
|||
pangea_sendcmd(hex,hn,"ping",-1,dp->hand.checkprod.bytes,sizeof(uint64_t),dp->hand.cardi,dp->hand.undergun); |
|||
hn->client->H.lastping = (uint32_t)time(NULL); |
|||
} |
|||
} |
|||
if ( dp->hand.handmask == ((1 << dp->N) - 1) && dp->hand.finished == 0 )//&& dp->hand.pangearake == 0 )
|
|||
{ |
|||
PNACL_message("P%d: all players folded or showed cards at %ld | rakemillis %d\n",hn->client->H.slot,(long)time(NULL),dp->rakemillis); |
|||
pangea_finish(hn,dp); |
|||
} |
|||
if ( hn->client->H.slot == pangea_slotA(dp->table) ) |
|||
pangea_serverstate(hn,dp,hn->server->H.privdata); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if ( n == 0 ) |
|||
break; |
|||
if ( m == 0 ) |
|||
usleep(3000); |
|||
} |
|||
//for (i=0; i<_PANGEA_MAXTHREADS; i++)
|
|||
// if ( THREADS[i] != 0 && Pangea_waiting != 0 )
|
|||
// pangea_userpoll(&THREADS[i]->hn);
|
|||
return(0); |
|||
}*/ |
|||
|
|||
char *_pangea_history(uint64_t my64bits,uint64_t tableid,cJSON *json) |
|||
{ |
|||
struct pangea_info *sp; |
|||
if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->dp != 0 ) |
|||
{ |
|||
if ( jobj(json,"handid") == 0 ) |
|||
return(pangea_dispsummary(sp,juint(json,"verbose"),sp->dp->summary,sp->dp->summarysize,tableid,sp->dp->numhands-1,sp->dp->N)); |
|||
else return(pangea_dispsummary(sp,juint(json,"verbose"),sp->dp->summary,sp->dp->summarysize,tableid,juint(json,"handid"),sp->dp->N)); |
|||
} |
|||
return(clonestr("{\"error\":\"cant find tableid\"}")); |
|||
} |
|||
|
|||
char *_pangea_buyin(uint64_t my64bits,uint64_t tableid,cJSON *json) |
|||
{ |
|||
struct pangea_info *sp; uint32_t buyin,vout; uint64_t amount = 0; char hex[1024],jsonstr[1024],*txidstr,*destaddr; |
|||
if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->dp != 0 && sp->tp != 0 && (amount= j64bits(json,"amount")) != 0 ) |
|||
{ |
|||
buyin = (uint32_t)(amount / sp->dp->bigblind); |
|||
PNACL_message("buyin.%u amount %.8f -> %.8f\n",buyin,dstr(amount),dstr(buyin * sp->bigblind)); |
|||
if ( buyin >= sp->dp->minbuyin && buyin <= sp->dp->maxbuyin ) |
|||
{ |
|||
sp->balances[pangea_ind(sp,sp->myslot)] = amount; |
|||
if ( (txidstr= jstr(json,"txidstr")) != 0 && (destaddr= jstr(json,"msigaddr")) != 0 && strcmp(destaddr,sp->multisigaddr) == 0 ) |
|||
{ |
|||
vout = juint(json,"vout"); |
|||
sprintf(jsonstr,"{\"txid\":\"%s\",\"vout\":%u,\"msig\":\"%s\",\"amount\":%.8f}",txidstr,vout,sp->multisigaddr,dstr(amount)); |
|||
pangea_sendcmd(hex,&sp->tp->hn,"addfunds",-1,(void *)jsonstr,(int32_t)strlen(jsonstr)+1,pangea_ind(sp,sp->myslot),-1); |
|||
} else pangea_sendcmd(hex,&sp->tp->hn,"addfunds",-1,(void *)&amount,sizeof(amount),pangea_ind(sp,sp->myslot),-1); |
|||
//pangea_sendcmd(hex,&sp->tp->hn,"addfunds",0,(void *)&amount,sizeof(amount),pangea_ind(sp,sp->myslot),-1);
|
|||
return(clonestr("{\"result\":\"buyin sent\"}")); |
|||
} |
|||
else |
|||
{ |
|||
PNACL_message("buyin.%d vs (%d %d)\n",buyin,sp->dp->minbuyin,sp->dp->maxbuyin); |
|||
return(clonestr("{\"error\":\"buyin too small or too big\"}")); |
|||
} |
|||
} |
|||
return(clonestr("{\"error\":\"cant buyin unless you are part of the table\"}")); |
|||
} |
|||
|
|||
char *_pangea_mode(uint64_t my64bits,uint64_t tableid,cJSON *json) |
|||
{ |
|||
struct pangea_info *sp; char *chatstr,hex[8192]; int32_t i; uint64_t pm; |
|||
if ( jobj(json,"automuck") != 0 ) |
|||
{ |
|||
if ( tableid == 0 ) |
|||
Showmode = juint(json,"automuck"); |
|||
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->priv != 0 ) |
|||
sp->priv->automuck = juint(json,"automuck"); |
|||
else return(clonestr("{\"error\":\"automuck not tableid or sp->priv\"}")); |
|||
return(clonestr("{\"result\":\"set automuck mode\"}")); |
|||
} |
|||
else if ( jobj(json,"autofold") != 0 ) |
|||
{ |
|||
if ( tableid == 0 ) |
|||
Autofold = juint(json,"autofold"); |
|||
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->priv != 0 ) |
|||
sp->priv->autofold = juint(json,"autofold"); |
|||
else return(clonestr("{\"error\":\"autofold not tableid or sp->priv\"}")); |
|||
return(clonestr("{\"result\":\"set autofold mode\"}")); |
|||
} |
|||
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && (chatstr= jstr(json,"chat")) != 0 && strlen(chatstr) < 256 ) |
|||
{ |
|||
if ( 0 && (pm= j64bits(json,"pm")) != 0 ) |
|||
{ |
|||
for (i=0; i<sp->numaddrs; i++) |
|||
if ( sp->addrs[i] == pm ) |
|||
break; |
|||
if ( i == sp->numaddrs ) |
|||
return(clonestr("{\"error\":\"specified pm destination not at table\"}")); |
|||
} else i = -1; |
|||
pangea_sendcmd(hex,&sp->tp->hn,"chat",i,(void *)chatstr,(int32_t)strlen(chatstr)+1,pangea_ind(sp,sp->myslot),-1); |
|||
return(clonestr("{\"result\":\"chat message sent\"}")); |
|||
} |
|||
return(clonestr("{\"error\":\"unknown pangea mode\"}")); |
|||
} |
|||
|
|||
void _pangea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind) |
|||
{ |
|||
PNACL_message(">>>>>>>>>>> CHAT FROM.%d %llu: (%s)\n",senderind,(long long)senderbits,(char *)buf); |
|||
} |
|||
|
|||
/*char *pangea_univ(uint8_t *mypriv,cJSON *json)
|
|||
{ |
|||
char *addrtypes[][3] = { {"BTC","0","80"}, {"LTC","48"}, {"BTCD","60","bc"}, {"DOGE","30"}, {"VRC","70"}, {"OPAL","115"}, {"BITS","25"} }; |
|||
char *wipstr,*coin,*coinaddr,pubkeystr[67],rsaddr[64],destaddr[64],wifbuf[128]; uint8_t priv[32],pub[33],addrtype; int32_t i; |
|||
uint64_t nxt64bits; cJSON *retjson,*item; |
|||
PNACL_message("inside rosetta\n"); |
|||
if ( (coin= jstr(json,"coin")) != 0 ) |
|||
{ |
|||
if ( (wipstr= jstr(json,"wif")) != 0 || (wipstr= jstr(json,"wip")) != 0 ) |
|||
{ |
|||
PNACL_message("got wip.(%s)\n",wipstr); |
|||
btc_wip2priv(priv,wipstr); |
|||
} |
|||
else if ( (coinaddr= jstr(json,"addr")) != 0 ) |
|||
{ |
|||
if ( getprivkey(priv,coin,coinaddr) < 0 ) |
|||
return(clonestr("{\"error\":\"cant get privkey\"}")); |
|||
} |
|||
} else memcpy(priv,mypriv,sizeof(priv)); |
|||
btc_priv2pub(pub,priv); |
|||
init_hexbytes_noT(pubkeystr,pub,33); |
|||
PNACL_message("pubkey.%s\n",pubkeystr); |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"btcpubkey",pubkeystr); |
|||
for (i=0; i<sizeof(addrtypes)/sizeof(*addrtypes); i++) |
|||
{ |
|||
if ( btc_coinaddr(destaddr,atoi(addrtypes[i][1]),pubkeystr) == 0 ) |
|||
{ |
|||
item = cJSON_CreateObject(); |
|||
jaddstr(item,"addr",destaddr); |
|||
if ( addrtypes[i][2] != 0 ) |
|||
{ |
|||
decode_hex(&addrtype,1,addrtypes[i][2]); |
|||
btc_priv2wip(wifbuf,priv,addrtype); |
|||
jaddstr(item,"wif",wifbuf); |
|||
} |
|||
jadd(retjson,addrtypes[i][0],item); |
|||
} |
|||
} |
|||
nxt64bits = nxt_priv2addr(rsaddr,pubkeystr,priv); |
|||
item = cJSON_CreateObject(); |
|||
jaddstr(item,"addressRS",rsaddr); |
|||
jadd64bits(item,"address",nxt64bits); |
|||
jaddstr(item,"pubkey",pubkeystr); |
|||
jadd(retjson,"NXT",item); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
*/ |
|||
|
|||
/*
|
|||
else if ( strcmp(methodstr,"newtable") == 0 ) |
|||
retstr = pangea_newtable(juint(json,"threadid"),json,plugin->nxt64bits,*(bits256 *)plugin->mypriv,*(bits256 *)plugin->mypub,plugin->transport,plugin->ipaddr,plugin->pangeaport,juint(json,"minbuyin"),juint(json,"maxbuyin"),juint(json,"rakemillis")); |
|||
else if ( sender == 0 || sender[0] == 0 ) |
|||
{ |
|||
if ( strcmp(methodstr,"start") == 0 ) |
|||
{ |
|||
strcpy(retbuf,"{\"result\":\"start issued\"}"); |
|||
if ( (base= jstr(json,"base")) != 0 ) |
|||
{ |
|||
if ( (maxplayers= juint(json,"maxplayers")) < 2 ) |
|||
maxplayers = 2; |
|||
else if ( maxplayers > CARDS777_MAXPLAYERS ) |
|||
maxplayers = CARDS777_MAXPLAYERS; |
|||
if ( jstr(json,"resubmit") == 0 ) |
|||
sprintf(retbuf,"{\"resubmit\":[{\"method\":\"start\"}, {\"bigblind\":\"%llu\"}, {\"ante\":\"%llu\"}, {\"rakemillis\":\"%u\"}, {\"maxplayers\":%d}, {\"minbuyin\":%d}, {\"maxbuyin\":%d}],\"pluginrequest\":\"SuperNET\",\"plugin\":\"InstantDEX\",\"method\":\"orderbook\",\"base\":\"%s\",\"exchange\":\"pangea\",\"allfields\":1}",(long long)j64bits(json,"bigblind"),(long long)j64bits(json,"ante"),juint(json,"rakemillis"),maxplayers,juint(json,"minbuyin"),juint(json,"maxbuyin"),jstr(json,"base")!=0?jstr(json,"base"):"BTCD"); |
|||
else if ( pangea_start(plugin,retbuf,base,0,j64bits(json,"bigblind"),j64bits(json,"ante"),juint(json,"rakemillis"),maxplayers,juint(json,"minbuyin"),juint(json,"maxbuyin"),json) < 0 ) |
|||
; |
|||
} else strcpy(retbuf,"{\"error\":\"no base specified\"}"); |
|||
} |
|||
else if ( strcmp(methodstr,"status") == 0 ) |
|||
retstr = pangea_status(plugin->nxt64bits,j64bits(json,"tableid"),json); |
|||
} |
|||
|
|||
int32_t pangea_unzbuf(uint8_t *buf,char *hexstr,int32_t len) |
|||
{ |
|||
int32_t i,j,len2; |
|||
for (len2=i=0; i<len; i+=2) |
|||
{ |
|||
if ( hexstr[i] == 'Z' ) |
|||
{ |
|||
for (j=0; j<hexstr[i+1]-'A'; j++) |
|||
buf[len2++] = 0; |
|||
} |
|||
else buf[len2++] = _decode_hex(&hexstr[i]); |
|||
} |
|||
//char *tmp = calloc(1,len*2+1);
|
|||
//init_hexbytes_noT(tmp,buf,len2);
|
|||
//PostMessage("zlen %d to len2 %d\n",len,len2);
|
|||
//free(tmp);
|
|||
return(len2); |
|||
} |
|||
|
|||
int32_t pangea_poll(uint64_t *senderbitsp,uint32_t *timestampp,union hostnet777 *hn) |
|||
{ |
|||
char *jsonstr,*hexstr,*cmdstr; cJSON *json; struct cards777_privdata *priv; struct cards777_pubdata *dp; struct pangea_info *sp; |
|||
int32_t len,senderind,maxlen; uint8_t *buf; |
|||
*senderbitsp = 0; |
|||
dp = hn->client->H.pubdata, sp = dp->table; |
|||
priv = hn->client->H.privdata; |
|||
if ( hn == 0 || hn->client == 0 || dp == 0 || priv == 0 ) |
|||
{ |
|||
if ( Debuglevel > 2 ) |
|||
PNACL_message("pangea_poll: null hn.%p %p dp.%p priv.%p\n",hn,hn!=0?hn->client:0,dp,priv); |
|||
return(-1); |
|||
} |
|||
maxlen = (int32_t)(sizeof(bits256) * dp->N*dp->N*dp->numcards); |
|||
if ( (buf= malloc(maxlen)) == 0 ) |
|||
{ |
|||
PNACL_message("pangea_poll: null buf\n"); |
|||
return(-1); |
|||
} |
|||
if ( dp != 0 && priv != 0 && (jsonstr= queue_dequeue(&hn->client->H.Q,1)) != 0 ) |
|||
{ |
|||
//pangea_neworder(dp,dp->table,0,0);
|
|||
//PNACL_message("player.%d GOT.(%s)\n",hn->client->H.slot,jsonstr);
|
|||
if ( (json= cJSON_Parse(jsonstr)) != 0 ) |
|||
{ |
|||
*senderbitsp = j64bits(json,"sender"); |
|||
if ( (senderind= juint(json,"myind")) < 0 || senderind >= dp->N ) |
|||
{ |
|||
PNACL_message("pangea_poll: illegal senderind.%d cardi.%d turni.%d (%s)\n",senderind,juint(json,"cardi"),juint(json,"turni"),jsonstr); |
|||
goto cleanup; |
|||
} |
|||
*timestampp = juint(json,"timestamp"); |
|||
hn->client->H.state = juint(json,"state"); |
|||
len = juint(json,"n"); |
|||
cmdstr = jstr(json,"cmd"); |
|||
if ( sp->myind < 0 ) |
|||
{ |
|||
// check for reactivation command
|
|||
goto cleanup; |
|||
} |
|||
if ( cmdstr != 0 && strcmp(cmdstr,"preflop") == 0 ) |
|||
{ |
|||
if ( (hexstr= jstr(json,"data")) != 0 ) |
|||
len = pangea_unzbuf(buf,hexstr,len); |
|||
} |
|||
else if ( (hexstr= jstr(json,"data")) != 0 && strlen(hexstr) == (len<<1) ) |
|||
{ |
|||
if ( len > maxlen ) |
|||
{ |
|||
PNACL_message("len too big for pangea_poll\n"); |
|||
goto cleanup; |
|||
} |
|||
decode_hex(buf,len,hexstr); |
|||
} else if ( hexstr != 0 ) |
|||
PNACL_message("len.%d vs hexlen.%ld (%s)\n",len,(long)(strlen(hexstr)>>1),hexstr); |
|||
if ( cmdstr != 0 ) |
|||
{ |
|||
if ( strcmp(cmdstr,"newhand") == 0 ) |
|||
pangea_newhand(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"ping") == 0 ) |
|||
pangea_ping(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"gotdeck") == 0 ) |
|||
pangea_gotdeck(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"ready") == 0 ) |
|||
pangea_ready(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"encoded") == 0 ) |
|||
pangea_encoded(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"final") == 0 ) |
|||
pangea_final(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"addfunds") == 0 ) |
|||
pangea_addfunds(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"preflop") == 0 ) |
|||
pangea_preflop(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"decoded") == 0 ) |
|||
pangea_decoded(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"card") == 0 ) |
|||
pangea_card(hn,json,dp,priv,buf,len,juint(json,"cardi"),senderind); |
|||
else if ( strcmp(cmdstr,"facedown") == 0 ) |
|||
pangea_facedown(hn,json,dp,priv,buf,len,juint(json,"cardi"),senderind); |
|||
else if ( strcmp(cmdstr,"faceup") == 0 ) |
|||
pangea_faceup(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"turn") == 0 ) |
|||
pangea_turn(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"confirmturn") == 0 ) |
|||
pangea_confirmturn(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"chat") == 0 ) |
|||
pangea_chat(*senderbitsp,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"action") == 0 ) |
|||
pangea_action(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"showdown") == 0 ) |
|||
pangea_showdown(hn,json,dp,priv,buf,len,senderind); |
|||
else if ( strcmp(cmdstr,"summary") == 0 ) |
|||
pangea_gotsummary(hn,json,dp,priv,buf,len,senderind); |
|||
} |
|||
cleanup: |
|||
free_json(json); |
|||
} |
|||
free_queueitem(jsonstr); |
|||
} |
|||
free(buf); |
|||
return(hn->client->H.state); |
|||
}*/ |
|||
|
|||
char *Pangea_bypass(uint64_t my64bits,uint8_t myprivkey[32],cJSON *json) |
|||
{ |
|||
char *methodstr,*retstr = 0; |
|||
if ( (methodstr= jstr(json,"method")) != 0 ) |
|||
{ |
|||
if ( strcmp(methodstr,"turn") == 0 ) |
|||
retstr = _pangea_input(my64bits,j64bits(json,"tableid"),json); |
|||
else if ( strcmp(methodstr,"status") == 0 ) |
|||
retstr = _pangea_status(my64bits,j64bits(json,"tableid"),json); |
|||
else if ( strcmp(methodstr,"mode") == 0 ) |
|||
retstr = _pangea_mode(my64bits,j64bits(json,"tableid"),json); |
|||
//else if ( strcmp(methodstr,"rosetta") == 0 )
|
|||
// retstr = pangea_univ(myprivkey,json);
|
|||
else if ( strcmp(methodstr,"buyin") == 0 ) |
|||
retstr = _pangea_buyin(my64bits,j64bits(json,"tableid"),json); |
|||
else if ( strcmp(methodstr,"history") == 0 ) |
|||
retstr = _pangea_history(my64bits,j64bits(json,"tableid"),json); |
|||
} |
|||
return(retstr); |
|||
} |
|||
|
|||
#include "../includes/iguana_apidefs.h" |
|||
|
|||
INT_AND_ARRAY(pangea,newhand,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,ping,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,gotdeck,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,ready,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,encoded,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,final,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,addedfunds,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,preflop,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,decoded,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,card,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,facedown,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,faceup,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,turn,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,confirmturn,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,chat,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,action,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,showdown,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
INT_AND_ARRAY(pangea,handsummary,senderind,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
|
|||
//U64_AND_ARRAY(pangea,turn,tableid,args);
|
|||
U64_AND_ARRAY(pangea,status,tableid,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
U64_AND_ARRAY(pangea,mode,tableid,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
U64_AND_ARRAY(pangea,buyin,tableid,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
U64_AND_ARRAY(pangea,history,tableid,args) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
#undef IGUANA_ARGS |
|||
|
|||
#include "../includes/iguana_apiundefs.h" |
File diff suppressed because it is too large
@ -0,0 +1,970 @@ |
|||
/******************************************************************************
|
|||
* 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" |
|||
|
|||
char *pangea_typestr(uint8_t type) |
|||
{ |
|||
static char err[64]; |
|||
switch ( type ) |
|||
{ |
|||
case 0xff: return("fold"); |
|||
case CARDS777_START: return("start"); |
|||
case CARDS777_ANTE: return("ante"); |
|||
case CARDS777_SMALLBLIND: return("smallblind"); |
|||
case CARDS777_BIGBLIND: return("bigblind"); |
|||
case CARDS777_CHECK: return("check"); |
|||
case CARDS777_CALL: return("call"); |
|||
case CARDS777_BET: return("bet"); |
|||
case CARDS777_RAISE: return("raise"); |
|||
case CARDS777_FULLRAISE: return("fullraise"); |
|||
case CARDS777_SENTCARDS: return("sentcards"); |
|||
case CARDS777_ALLIN: return("allin"); |
|||
case CARDS777_FACEUP: return("faceup"); |
|||
case CARDS777_WINNINGS: return("won"); |
|||
case CARDS777_RAKES: return("rakes"); |
|||
case CARDS777_CHANGES: return("changes"); |
|||
case CARDS777_SNAPSHOT: return("snapshot"); |
|||
} |
|||
sprintf(err,"unknown type.%d",type); |
|||
return(err); |
|||
} |
|||
|
|||
cJSON *pangea_handitem(int32_t *cardip,cJSON **pitemp,uint8_t type,uint64_t valA,uint64_t *bits64p,bits256 card,int32_t numplayers) |
|||
{ |
|||
int32_t cardi,n,i,rebuy,busted; char str[128],hexstr[65],cardpubs[(CARDS777_MAXCARDS+1)*64+1]; cJSON *item,*array,*pitem = 0; |
|||
item = cJSON_CreateObject(); |
|||
*cardip = -1; |
|||
switch ( type ) |
|||
{ |
|||
case CARDS777_START: |
|||
jaddnum(item,"handid",valA); |
|||
init_hexbytes_noT(cardpubs,(void *)bits64p,(int32_t)((CARDS777_MAXCARDS+1) * sizeof(bits256))); |
|||
jaddstr(item,"cardpubs",cardpubs); |
|||
break; |
|||
case CARDS777_RAKES: |
|||
jaddnum(item,"hostrake",dstr(valA)); |
|||
jaddnum(item,"pangearake",dstr(*bits64p)); |
|||
break; |
|||
case CARDS777_SNAPSHOT: |
|||
jaddnum(item,"handid",valA); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<CARDS777_MAXPLAYERS; i++) |
|||
{ |
|||
if ( i < numplayers ) |
|||
jaddinum(array,dstr(bits64p[i])); |
|||
else jaddinum(array,dstr(0)); |
|||
} |
|||
jadd(item,"snapshot",array); |
|||
//printf("add snapshot for numplayers.%d\n",numplayers);
|
|||
break; |
|||
case CARDS777_CHANGES: |
|||
n = (int32_t)(valA & 0xf); |
|||
busted = (int32_t)((valA>>4) & 0xffff); |
|||
rebuy = (int32_t)((valA>>20) & 0xffff); |
|||
if ( busted != 0 ) |
|||
jaddnum(item,"busted",busted); |
|||
if ( rebuy != 0 ) |
|||
jaddnum(item,"rebuy",rebuy); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<n; i++) |
|||
jaddinum(array,dstr(bits64p[i])); |
|||
jadd(item,"balances",array); |
|||
break; |
|||
case CARDS777_WINNINGS: |
|||
if ( (int32_t)valA >= 0 && valA < numplayers ) |
|||
jaddnum(item,"player",valA); |
|||
jaddnum(item,"won",dstr(*bits64p)); |
|||
if ( pitem == 0 ) |
|||
pitem = cJSON_CreateObject(); |
|||
jaddnum(pitem,"won",dstr(*bits64p)); |
|||
break; |
|||
case CARDS777_FACEUP: |
|||
*cardip = cardi = (int32_t)(valA >> 8); |
|||
if ( cardi >= 0 && cardi < 52 ) |
|||
jaddnum(item,"cardi",cardi); |
|||
else printf("illegal cardi.%d valA.%llu\n",cardi,(long long)valA); |
|||
valA &= 0xff; |
|||
if ( (int32_t)valA >= 0 && valA < numplayers ) |
|||
jaddnum(item,"player",valA); |
|||
else if ( valA == 0xff ) |
|||
jaddnum(item,"community",cardi - numplayers*2); |
|||
cardstr(str,card.bytes[1]); |
|||
jaddnum(item,str,card.bytes[1]); |
|||
init_hexbytes_noT(hexstr,card.bytes,sizeof(card)); |
|||
jaddstr(item,"privkey",hexstr); |
|||
break; |
|||
default: |
|||
if ( (int32_t)valA >= 0 && valA < numplayers ) |
|||
jaddnum(item,"player",valA); |
|||
jaddstr(item,"action",pangea_typestr(type)); |
|||
if ( pitem == 0 ) |
|||
pitem = cJSON_CreateObject(); |
|||
if ( *bits64p != 0 ) |
|||
{ |
|||
jaddnum(item,"bet",dstr(*bits64p)); |
|||
jaddnum(pitem,pangea_typestr(type),dstr(*bits64p)); |
|||
} |
|||
else jaddstr(pitem,"action",pangea_typestr(type)); |
|||
break; |
|||
} |
|||
*pitemp = pitem; |
|||
return(item); |
|||
} |
|||
|
|||
int32_t pangea_parsesummary(uint8_t *typep,uint64_t *valAp,uint64_t *bits64p,bits256 *cardp,uint8_t *summary,int32_t len) |
|||
{ |
|||
int32_t handid; uint16_t cardi_player; uint32_t changes=0; uint8_t player; |
|||
*bits64p = 0; |
|||
memset(cardp,0,sizeof(*cardp)); |
|||
len += SuperNET_copybits(1,&summary[len],(void *)typep,sizeof(*typep)); |
|||
if ( *typep == 0 ) |
|||
{ |
|||
printf("len.%d type.%d [%d]\n",len,*typep,summary[len-1]); |
|||
return(-1); |
|||
} |
|||
if ( *typep == CARDS777_START || *typep == CARDS777_SNAPSHOT ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)&handid,sizeof(handid)), *valAp = handid; |
|||
else if ( *typep == CARDS777_CHANGES ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)&changes,sizeof(changes)), *valAp = changes; |
|||
else if ( *typep == CARDS777_RAKES ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)valAp,sizeof(*valAp)); |
|||
else if ( *typep == CARDS777_FACEUP ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)&cardi_player,sizeof(cardi_player)), *valAp = cardi_player; |
|||
else len += SuperNET_copybits(1,&summary[len],(void *)&player,sizeof(player)), *valAp = player; |
|||
if ( *typep == CARDS777_FACEUP ) |
|||
len += SuperNET_copybits(1,&summary[len],cardp->bytes,sizeof(*cardp)); |
|||
else if ( *typep == CARDS777_START ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(bits256)*(CARDS777_MAXCARDS+1)); |
|||
else if ( *typep == CARDS777_SNAPSHOT ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p) * CARDS777_MAXPLAYERS); |
|||
else if ( *typep == CARDS777_CHANGES ) |
|||
len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p) * (changes & 0xf)); |
|||
else len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p)); |
|||
return(len); |
|||
} |
|||
|
|||
void pangea_summary(union pangeanet777 *hn,struct cards777_pubdata *dp,uint8_t type,void *arg0,int32_t size0,void *arg1,int32_t size1) |
|||
{ |
|||
uint64_t valA,bits64[CARDS777_MAXPLAYERS + (CARDS777_MAXCARDS+1)*4]; bits256 card; uint8_t checktype; char *str; |
|||
cJSON *item,*pitem; int32_t len,cardi,startlen = dp->summarysize; |
|||
if ( type == 0 ) |
|||
{ |
|||
printf("type.0\n"); getchar(); |
|||
} |
|||
//printf("summarysize.%d type.%d [%02x %02x]\n",dp->summarysize,type,*(uint8_t *)arg0,*(uint8_t *)arg1);
|
|||
dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],(void *)&type,sizeof(type)); |
|||
//printf("-> %d\n",dp->summary[dp->summarysize-1]);
|
|||
dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],arg0,size0); |
|||
dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],arg1,size1); |
|||
//printf("startlen.%d summarysize.%d\n",startlen,dp->summarysize);
|
|||
len = pangea_parsesummary(&checktype,&valA,bits64,&card,dp->summary,startlen); |
|||
if ( len != dp->summarysize || checktype != type || memcmp(&valA,arg0,size0) != 0 ) |
|||
printf("pangea_summary parse error [%d] (%d vs %d) || (%d vs %d).%d || cmp.%d size0.%d size1.%d\n",startlen,len,dp->summarysize,checktype,type,dp->summary[startlen],memcmp(&valA,arg0,size0),size0,size1); |
|||
if ( card.txid != 0 && memcmp(card.bytes,arg1,sizeof(card)) != 0 ) |
|||
printf("pangea_summary: parse error card mismatch %llx != %llx\n",(long long)card.txid,*(long long *)arg1); |
|||
else if ( card.txid == 0 && memcmp(arg1,bits64,size1) != 0 ) |
|||
printf("pangea_summary: parse error bits64 %llx != %llx\n",(long long)bits64[0],*(long long *)arg0); |
|||
if ( 1 && hn->client->H.slot == pangea_slotA(dp->table) ) |
|||
{ |
|||
if ( (item= pangea_handitem(&cardi,&pitem,type,valA,bits64,card,dp->N)) != 0 ) |
|||
{ |
|||
str = jprint(item,1); |
|||
printf("ITEM.(%s)\n",str); |
|||
free(str); |
|||
} |
|||
if ( pitem != 0 ) |
|||
{ |
|||
str = jprint(pitem,1); |
|||
printf("PITEM.(%s)\n",str); |
|||
free(str); |
|||
} |
|||
} |
|||
if ( Debuglevel > 2 )//|| hn->client->H.slot == pangea_slotA(dp->table) )
|
|||
printf("pangea_summary.%d %d | summarysize.%d crc.%u\n",type,*(uint8_t *)arg0,dp->summarysize,calc_crc32(0,dp->summary,dp->summarysize)); |
|||
} |
|||
|
|||
char *pangea_dispsummary(struct pangea_info *sp,int32_t verbose,uint8_t *summary,int32_t summarysize,uint64_t tableid,int32_t handid,int32_t numplayers) |
|||
{ |
|||
int32_t i,cardi,n = 0,len = 0; uint8_t type; uint64_t valA,bits64[CARDS777_MAXPLAYERS + (CARDS777_MAXCARDS+1)*4]; bits256 card; |
|||
cJSON *item,*json,*all,*cardis[52],*players[CARDS777_MAXPLAYERS],*pitem,*array = cJSON_CreateArray(); |
|||
all = cJSON_CreateArray(); |
|||
memset(cardis,0,sizeof(cardis)); |
|||
memset(players,0,sizeof(players)); |
|||
for (i=0; i<numplayers; i++) |
|||
players[i] = cJSON_CreateArray(); |
|||
while ( len < summarysize ) |
|||
{ |
|||
memset(bits64,0,sizeof(bits64)); |
|||
len = pangea_parsesummary(&type,&valA,bits64,&card,summary,len); |
|||
if ( (item= pangea_handitem(&cardi,&pitem,type,valA,bits64,card,numplayers)) != 0 ) |
|||
{ |
|||
if ( cardi >= 0 && cardi < 52 ) |
|||
{ |
|||
//printf("cardis[%d] <- %p\n",cardi,item);
|
|||
cardis[cardi] = item; |
|||
} |
|||
else jaddi(array,item); |
|||
item = 0; |
|||
} |
|||
if ( pitem != 0 ) |
|||
{ |
|||
jaddnum(pitem,"n",n), n++; |
|||
if ( (int32_t)valA >= 0 && valA < numplayers ) |
|||
jaddi(players[valA],pitem); |
|||
else free_json(pitem), printf("illegal player.%llu\n",(long long)valA); |
|||
pitem = 0; |
|||
} |
|||
} |
|||
for (i=0; i<numplayers; i++) |
|||
jaddi(all,players[i]); |
|||
if ( verbose == 0 ) |
|||
{ |
|||
for (i=0; i<52; i++) |
|||
if ( cardis[i] != 0 ) |
|||
free_json(cardis[i]); |
|||
free_json(array); |
|||
return(jprint(all,1)); |
|||
} |
|||
else |
|||
{ |
|||
json = cJSON_CreateObject(); |
|||
if ( tableid != 0 ) |
|||
jadd64bits(json,"tableid",tableid); |
|||
if ( 0 && sp != 0 ) |
|||
{ |
|||
//array = cJSON_CreateArray();
|
|||
//for (i=0; i<sp->numactive; i++)
|
|||
// jaddi64bits(array,sp->active[i]);
|
|||
//jadd(json,"active",array);
|
|||
for (i=0; i<sp->numactive; i++) |
|||
printf("%llu ",(long long)sp->active[i]); |
|||
printf("sp->numactive[%d]\n",sp->numactive); |
|||
} |
|||
jaddnum(json,"size",summarysize); |
|||
jaddnum(json,"handid",handid); |
|||
//jaddnum(json,"crc",_crc32(0,summary,summarysize));
|
|||
jadd(json,"hand",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<52; i++) |
|||
if ( cardis[i] != 0 ) |
|||
jaddi(array,cardis[i]); |
|||
jadd(json,"cards",array); |
|||
//jadd(json,"players",all);
|
|||
return(jprint(json,1)); |
|||
} |
|||
} |
|||
|
|||
void pangea_fold(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player) |
|||
{ |
|||
uint8_t tmp; |
|||
//printf("player.%d folded\n",player); //getchar();
|
|||
dp->hand.handmask |= (1 << player); |
|||
dp->hand.betstatus[player] = CARDS777_FOLD; |
|||
dp->hand.actions[player] = CARDS777_FOLD; |
|||
tmp = player; |
|||
pangea_summary(hn,dp,CARDS777_FOLD,&tmp,sizeof(tmp),(void *)&dp->hand.bets[player],sizeof(dp->hand.bets[player])); |
|||
} |
|||
|
|||
uint64_t pangea_totalbet(struct cards777_pubdata *dp) |
|||
{ |
|||
int32_t j; uint64_t total; |
|||
for (total=j=0; j<dp->N; j++) |
|||
total += dp->hand.bets[j]; |
|||
return(total); |
|||
} |
|||
|
|||
int32_t pangea_actives(int32_t *activej,struct cards777_pubdata *dp) |
|||
{ |
|||
int32_t i,n; |
|||
*activej = -1; |
|||
for (i=n=0; i<dp->N; i++) |
|||
{ |
|||
if ( dp->hand.betstatus[i] != CARDS777_FOLD ) |
|||
{ |
|||
if ( *activej < 0 ) |
|||
*activej = i; |
|||
n++; |
|||
} |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
struct pangea_info *pangea_usertables(int32_t *nump,uint64_t my64bits,uint64_t tableid) |
|||
{ |
|||
int32_t i,j,num = 0; struct pangea_info *sp,*retsp = 0; |
|||
*nump = 0; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
{ |
|||
if ( (sp= TABLES[i]) != 0 ) |
|||
{ |
|||
for (j=0; j<sp->numaddrs; j++) |
|||
if ( sp->addrs[j] == my64bits && (tableid == 0 || sp->tableid == tableid) ) |
|||
{ |
|||
if ( num++ == 0 ) |
|||
{ |
|||
retsp = sp; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
*nump = num; |
|||
return(retsp); |
|||
} |
|||
|
|||
struct pangea_info *pangea_threadtables(int32_t *nump,int32_t threadid,uint64_t tableid) |
|||
{ |
|||
int32_t i,j,num = 0; struct pangea_info *sp,*retsp = 0; |
|||
*nump = 0; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
{ |
|||
if ( (sp= TABLES[i]) != 0 ) |
|||
{ |
|||
for (j=0; j<sp->numaddrs; j++) |
|||
if ( sp->tp != 0 && sp->tp->threadid == threadid && (tableid == 0 || sp->tableid == tableid) ) |
|||
{ |
|||
if ( num++ == 0 ) |
|||
{ |
|||
retsp = sp; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
*nump = num; |
|||
return(retsp); |
|||
} |
|||
|
|||
int32_t pangea_bet(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player,int64_t bet,int32_t action) |
|||
{ |
|||
uint64_t sum; uint8_t tmp; struct pangea_info *sp = dp->table; |
|||
player %= dp->N; |
|||
if ( Debuglevel > 2 ) |
|||
printf("player.%d PANGEA_BET[%d] <- %.8f\n",hn->client->H.slot,player,dstr(bet)); |
|||
if ( dp->hand.betstatus[player] == CARDS777_ALLIN ) |
|||
return(CARDS777_ALLIN); |
|||
else if ( dp->hand.betstatus[player] == CARDS777_FOLD ) |
|||
return(CARDS777_FOLD); |
|||
if ( bet > 0 && bet >= sp->balances[pangea_slot(sp,player)] ) |
|||
{ |
|||
bet = sp->balances[pangea_slot(sp,player)]; |
|||
dp->hand.betstatus[player] = action = CARDS777_ALLIN; |
|||
} |
|||
else |
|||
{ |
|||
if ( bet > dp->hand.betsize && bet > dp->hand.lastraise && bet < (dp->hand.lastraise<<1) ) |
|||
{ |
|||
printf("pangea_bet %.8f not double %.8f, clip to lastraise\n",dstr(bet),dstr(dp->hand.lastraise)); |
|||
bet = dp->hand.lastraise; |
|||
action = CARDS777_RAISE; |
|||
} |
|||
} |
|||
sum = dp->hand.bets[player]; |
|||
if ( sum+bet < dp->hand.betsize && action != CARDS777_ALLIN ) |
|||
{ |
|||
pangea_fold(hn,dp,player); |
|||
action = CARDS777_FOLD; |
|||
tmp = player; |
|||
if ( Debuglevel > 2 ) |
|||
printf("player.%d betsize %.8f < hand.betsize %.8f FOLD\n",player,dstr(bet),dstr(dp->hand.betsize)); |
|||
return(action); |
|||
} |
|||
else if ( bet >= 2*dp->hand.lastraise ) |
|||
{ |
|||
dp->hand.lastraise = bet; |
|||
dp->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); |
|||
} |
|||
} |
|||
sum += bet; |
|||
if ( sum > dp->hand.betsize ) |
|||
{ |
|||
dp->hand.numactions = 0; |
|||
dp->hand.betsize = sum, dp->hand.lastbettor = player; |
|||
if ( sum > dp->hand.lastraise && action == CARDS777_ALLIN ) |
|||
dp->hand.lastraise = sum; |
|||
else if ( action == CARDS777_CHECK ) |
|||
action = CARDS777_BET; |
|||
} |
|||
if ( bet > 0 && action == CARDS777_CHECK ) |
|||
action = CARDS777_CALL; |
|||
tmp = player; |
|||
pangea_summary(hn,dp,action,&tmp,sizeof(tmp),(void *)&bet,sizeof(bet)); |
|||
sp->balances[pangea_slot(sp,player)] -= bet, dp->hand.bets[pangea_slot(sp,player)] += bet; |
|||
if ( Debuglevel > 2 ) |
|||
printf("player.%d: player.%d BET %f -> balances %f bets %f\n",hn->client->H.slot,player,dstr(bet),dstr(sp->balances[pangea_slot(sp,player)]),dstr(dp->hand.bets[player])); |
|||
return(action); |
|||
} |
|||
|
|||
void pangea_antes(union pangeanet777 *hn,struct cards777_pubdata *dp) |
|||
{ |
|||
int32_t i,j,n,actives[CARDS777_MAXPLAYERS]; uint64_t threshold; int32_t handid; struct pangea_info *sp = dp->table; |
|||
for (i=0; i<sp->numaddrs; i++) |
|||
dp->snapshot[i] = sp->balances[i]; |
|||
handid = dp->numhands - 1; |
|||
pangea_summary(hn,dp,CARDS777_SNAPSHOT,(void *)&handid,sizeof(handid),(void *)dp->snapshot,sizeof(uint64_t)*CARDS777_MAXPLAYERS); |
|||
for (i=0; i<dp->N; i++) |
|||
if ( sp->balances[pangea_slot(sp,i)] <= 0 ) |
|||
pangea_fold(hn,dp,i); |
|||
if ( dp->ante != 0 ) |
|||
{ |
|||
for (i=0; i<dp->N; i++) |
|||
{ |
|||
if ( i != dp->button && i != (dp->button+1) % dp->N ) |
|||
{ |
|||
if ( sp->balances[pangea_slot(sp,i)] < dp->ante ) |
|||
pangea_fold(hn,dp,i); |
|||
else pangea_bet(hn,dp,i,dp->ante,CARDS777_ANTE); |
|||
} |
|||
} |
|||
} |
|||
memset(actives,0,sizeof(actives)); |
|||
for (i=n=0; i<dp->N; i++) |
|||
{ |
|||
j = (1 + dp->button + i) % dp->N; |
|||
if ( n == 0 ) |
|||
threshold = (dp->bigblind >> 1) - 1; |
|||
else if ( n == 1 ) |
|||
threshold = dp->bigblind - 1; |
|||
else threshold = 0; |
|||
if ( sp->balances[pangea_slot(sp,j)] > threshold ) |
|||
{ |
|||
//printf("active[%d] <- %d\n",n,j);
|
|||
actives[n++] = j; |
|||
} |
|||
else pangea_fold(hn,dp,j); |
|||
} |
|||
if ( n < 2 ) |
|||
{ |
|||
printf("pangea_antes not enough players n.%d\n",n); |
|||
} |
|||
else |
|||
{ |
|||
pangea_bet(hn,dp,actives[0],(dp->bigblind>>1),CARDS777_SMALLBLIND); |
|||
dp->button = (actives[0] + dp->N - 1) % dp->N; |
|||
pangea_bet(hn,dp,actives[1],dp->bigblind,CARDS777_BIGBLIND); |
|||
|
|||
} |
|||
/*for (i=0; i<dp->N; i++)
|
|||
{ |
|||
j = (1 + dp->button + i) % dp->N; |
|||
if ( dp->balances[j] < (dp->bigblind >> 1) ) |
|||
pangea_fold(hn,dp,j); |
|||
else |
|||
{ |
|||
smallblindi = j; |
|||
pangea_bet(hn,dp,smallblindi,(dp->bigblind>>1),CARDS777_SMALLBLIND); |
|||
break; |
|||
} |
|||
} |
|||
for (i=0; i<dp->N; i++) |
|||
{ |
|||
j = (1 + smallblindi + i) % dp->N; |
|||
if ( dp->balances[j] < dp->bigblind ) |
|||
pangea_fold(hn,dp,j); |
|||
else |
|||
{ |
|||
pangea_bet(hn,dp,j,dp->bigblind,CARDS777_BIGBLIND); |
|||
break; |
|||
} |
|||
}*/ |
|||
if ( 0 ) |
|||
{ |
|||
for (i=0; i<dp->N; i++) |
|||
printf("%.8f ",dstr(dp->hand.bets[i])); |
|||
printf("antes\n"); |
|||
} |
|||
} |
|||
|
|||
void pangea_checkantes(union pangeanet777 *hn,struct cards777_pubdata *dp) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<dp->N; i++) |
|||
{ |
|||
//printf("%.8f ",dstr(dp->balances[i]));
|
|||
if ( dp->hand.bets[i] != 0 ) |
|||
break; |
|||
} |
|||
if ( i == dp->N && dp->hand.checkprod.txid != 0 ) |
|||
{ |
|||
for (i=0; i<dp->N; i++) |
|||
if ( dp->hand.bets[i] != 0 ) |
|||
break; |
|||
if ( i == dp->N ) |
|||
{ |
|||
//printf("i.%d vs N.%d call antes\n",i,dp->N);
|
|||
pangea_antes(hn,dp); |
|||
} else printf("bets i.%d\n",i); |
|||
} |
|||
} |
|||
|
|||
/*int32_t pangea_cashout(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
|
|||
{ |
|||
return(0); |
|||
}*/ |
|||
|
|||
int32_t _pangea_addfunds(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) |
|||
{ |
|||
char *txidstr,*destaddr; uint32_t vout; int32_t slot; uint64_t amount = 0; struct pangea_info *sp = dp->table; |
|||
slot = pangea_slot(sp,senderind); |
|||
if ( datalen == sizeof(amount) ) |
|||
memcpy(&amount,data,sizeof(amount)); |
|||
else |
|||
{ |
|||
if ( (json= cJSON_Parse((void *)data)) != 0 ) |
|||
{ |
|||
amount = j64bits(json,"amount"); |
|||
txidstr = jstr(json,"txidstr"); |
|||
destaddr = jstr(json,"msigaddr"); |
|||
vout = juint(json,"vout"); |
|||
if ( txidstr != 0 && destaddr != 0 && amount > 0 && strcmp(destaddr,sp->multisigaddr) == 0 ) |
|||
{ |
|||
// of course need to verify on blockchain
|
|||
strcpy(sp->buyintxids[slot],txidstr); |
|||
sp->buyinvouts[slot] = vout; |
|||
sp->buyinamounts[slot] = amount; |
|||
} |
|||
free_json(json); |
|||
} |
|||
} |
|||
if ( sp->balances[slot] == 0 ) |
|||
sp->balances[slot] = amount; |
|||
pangea_checkantes(hn,dp); |
|||
printf("slot.%d: addfunds.%d <- %.8f total %.8f\n",hn->client->H.slot,senderind,dstr(amount),dstr(sp->balances[senderind])); |
|||
return(0); |
|||
} |
|||
|
|||
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(int32_t dispflag,uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],struct cards777_pubdata *dp,int64_t *bets) |
|||
{ |
|||
int32_t i,j,nonz,n = 0; uint64_t bet,minbet = 0; |
|||
memset(sidepots,0,sizeof(uint64_t)*CARDS777_MAXPLAYERS*CARDS777_MAXPLAYERS); |
|||
for (j=0; j<dp->N; j++) |
|||
sidepots[0][j] = bets[j]; |
|||
nonz = 1; |
|||
while ( nonz > 0 ) |
|||
{ |
|||
for (minbet=j=0; j<dp->N; j++) |
|||
{ |
|||
if ( (bet= sidepots[n][j]) != 0 ) |
|||
{ |
|||
if ( dp->hand.betstatus[j] != CARDS777_FOLD ) |
|||
{ |
|||
if ( minbet == 0 || bet < minbet ) |
|||
minbet = bet; |
|||
} |
|||
} |
|||
} |
|||
for (j=nonz=0; j<dp->N; j++) |
|||
{ |
|||
if ( sidepots[n][j] > minbet && dp->hand.betstatus[j] != CARDS777_FOLD ) |
|||
nonz++; |
|||
} |
|||
if ( nonz > 0 ) |
|||
{ |
|||
for (j=0; j<dp->N; j++) |
|||
{ |
|||
if ( sidepots[n][j] > minbet ) |
|||
{ |
|||
sidepots[n+1][j] = (sidepots[n][j] - minbet); |
|||
sidepots[n][j] = minbet; |
|||
} |
|||
} |
|||
} |
|||
if ( ++n >= dp->N ) |
|||
break; |
|||
} |
|||
if ( dispflag != 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
for (j=0; j<dp->N; j++) |
|||
printf("%.8f ",dstr(sidepots[i][j])); |
|||
printf("sidepot.%d of %d\n",i,n); |
|||
} |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
int64_t pangea_splitpot(int64_t *won,uint64_t *pangearakep,uint64_t sidepot[CARDS777_MAXPLAYERS],union pangeanet777 *hn,int32_t rakemillis) |
|||
{ |
|||
int32_t winners[CARDS777_MAXPLAYERS],j,n,numwinners = 0; uint32_t bestrank,rank; uint8_t tmp; struct pangea_info *sp; |
|||
uint64_t total = 0,bet,split,maxrake,rake=0,pangearake=0; char handstr[128],besthandstr[128]; struct cards777_pubdata *dp; |
|||
dp = hn->client->H.pubdata, sp = dp->table; |
|||
bestrank = 0; |
|||
besthandstr[0] = 0; |
|||
for (j=n=0; j<dp->N; j++) |
|||
{ |
|||
if ( (bet= sidepot[j]) != 0 ) |
|||
{ |
|||
total += bet; |
|||
if ( dp->hand.betstatus[j] != CARDS777_FOLD ) |
|||
{ |
|||
if ( dp->hand.handranks[j] > bestrank ) |
|||
{ |
|||
bestrank = dp->hand.handranks[j]; |
|||
set_handstr(besthandstr,dp->hand.hands[j],0); |
|||
//printf("set besthandstr.(%s)\n",besthandstr);
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
for (j=0; j<dp->N; j++) |
|||
{ |
|||
if ( dp->hand.betstatus[j] != CARDS777_FOLD && sidepot[j] > 0 ) |
|||
{ |
|||
if ( dp->hand.handranks[j] == bestrank ) |
|||
winners[numwinners++] = j; |
|||
rank = set_handstr(handstr,dp->hand.hands[j],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<dp->N; j++) |
|||
if ( dp->hand.bets[j] > 0 ) |
|||
n++; |
|||
if ( (maxrake= maxrakes[n] * dp->bigblind) > dp->maxrake ) |
|||
{ |
|||
maxrake = dp->maxrake; |
|||
if ( strcmp(dp->coinstr,"BTC") == 0 && maxrake < PANGEA_BTCMAXRAKE ) |
|||
maxrake = PANGEA_BTCMAXRAKE; |
|||
else if ( maxrake < PANGEA_MAXRAKE ) |
|||
maxrake = PANGEA_MAXRAKE; |
|||
} |
|||
split = pangea_winnings(pangea_ind(dp->table,hn->client->H.slot),&pangearake,&rake,total,numwinners,rakemillis,maxrake); |
|||
(*pangearakep) += pangearake; |
|||
for (j=0; j<numwinners; j++) |
|||
{ |
|||
tmp = winners[j]; |
|||
pangea_summary(hn,dp,CARDS777_WINNINGS,&tmp,sizeof(tmp),(void *)&split,sizeof(split)); |
|||
sp->balances[pangea_slot(sp,winners[j])] += split; |
|||
won[winners[j]] += 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,dp->numhands); |
|||
for (j=0; j<numwinners; j++) |
|||
printf("%d ",pangea_slot(sp,winners[j])); |
|||
printf("\n"); |
|||
} |
|||
} |
|||
return(rake); |
|||
} |
|||
|
|||
uint64_t pangea_bot(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t turni,int32_t cardi,uint64_t betsize) |
|||
{ |
|||
int32_t r,action=CARDS777_CHECK,n,activej; char hex[1024]; uint64_t threshold,total,sum,amount = 0; struct pangea_info *sp = dp->table; |
|||
sum = dp->hand.bets[pangea_ind(dp->table,hn->client->H.slot)]; |
|||
action = 0; |
|||
n = pangea_actives(&activej,dp); |
|||
if ( (r = (rand() % 100)) < 1 ) |
|||
amount = sp->balances[hn->client->H.slot], action = CARDS777_ALLIN; |
|||
else |
|||
{ |
|||
if ( betsize == sum ) |
|||
{ |
|||
if ( r < 100/n ) |
|||
{ |
|||
amount = dp->hand.lastraise; |
|||
action = 1; |
|||
if ( (rand() % 100) < 10 ) |
|||
amount <<= 1; |
|||
} |
|||
} |
|||
else if ( betsize > sum ) |
|||
{ |
|||
amount = (betsize - sum); |
|||
total = pangea_totalbet(dp); |
|||
threshold = (300 * amount)/(1 + total); |
|||
n++; |
|||
if ( r/n > threshold ) |
|||
{ |
|||
action = 1; |
|||
if ( r/n > 3*threshold && amount < dp->hand.lastraise*2 ) |
|||
amount = dp->hand.lastraise * 2, action = 2; |
|||
//else if ( r/n > 10*threshold )
|
|||
// amount = dp->balances[pangea_ind(dp->table,hn->client->H.slot)], action = CARDS777_ALLIN;
|
|||
} |
|||
else if ( amount < sum/10 || amount <= SATOSHIDEN ) |
|||
action = CARDS777_CALL; |
|||
else |
|||
{ |
|||
//printf("amount %.8f, sum %.8f, betsize %.8f\n",dstr(amount),dstr(sum),dstr(betsize));
|
|||
action = CARDS777_FOLD, amount = 0; |
|||
} |
|||
} |
|||
else printf("pangea_turn error betsize %.8f vs sum %.8f | slot.%d ind.%d\n",dstr(betsize),dstr(sum),hn->client->H.slot,pangea_ind(dp->table,hn->client->H.slot)); |
|||
if ( amount > sp->balances[hn->client->H.slot] ) |
|||
amount = sp->balances[hn->client->H.slot], action = CARDS777_ALLIN; |
|||
} |
|||
pangea_sendcmd(hex,hn,"action",-1,(void *)&amount,sizeof(amount),cardi,action); |
|||
printf("playerbot.%d got pangea_turn.%d for player.%d action.%d bet %.8f\n",hn->client->H.slot,cardi,turni,action,dstr(amount)); |
|||
return(amount); |
|||
} |
|||
|
|||
cJSON *pangea_handjson(struct cards777_handinfo *hand,uint8_t *holecards,int32_t isbot) |
|||
{ |
|||
int32_t i,card; char cardAstr[8],cardBstr[8],pairstr[18],cstr[128]; cJSON *array,*json = cJSON_CreateObject(); |
|||
array = cJSON_CreateArray(); |
|||
cstr[0] = 0; |
|||
for (i=0; i<5; i++) |
|||
{ |
|||
if ( (card= hand->community[i]) != 0xff ) |
|||
{ |
|||
jaddinum(array,card); |
|||
cardstr(&cstr[strlen(cstr)],card); |
|||
strcat(cstr," "); |
|||
} |
|||
} |
|||
jaddstr(json,"community",cstr); |
|||
jadd(json,"cards",array); |
|||
if ( (card= holecards[0]) != 0xff ) |
|||
{ |
|||
jaddnum(json,"cardA",card); |
|||
cardstr(cardAstr,holecards[0]); |
|||
} else cardAstr[0] = 0; |
|||
if ( (card= holecards[1]) != 0xff ) |
|||
{ |
|||
jaddnum(json,"cardB",card); |
|||
cardstr(cardBstr,holecards[1]); |
|||
} else cardBstr[0] = 0; |
|||
sprintf(pairstr,"%s %s",cardAstr,cardBstr); |
|||
jaddstr(json,"holecards",pairstr); |
|||
jaddnum(json,"betsize",dstr(hand->betsize)); |
|||
jaddnum(json,"lastraise",dstr(hand->lastraise)); |
|||
jaddnum(json,"lastbettor",hand->lastbettor); |
|||
jaddnum(json,"numactions",hand->numactions); |
|||
jaddnum(json,"undergun",hand->undergun); |
|||
jaddnum(json,"isbot",isbot); |
|||
jaddnum(json,"cardi",hand->cardi); |
|||
return(json); |
|||
} |
|||
|
|||
char *pangea_statusstr(int32_t status) |
|||
{ |
|||
if ( status == CARDS777_FOLD ) |
|||
return("folded"); |
|||
else if ( status == CARDS777_ALLIN ) |
|||
return("ALLin"); |
|||
else return("active"); |
|||
} |
|||
|
|||
int32_t pangea_countdown(struct cards777_pubdata *dp,int32_t player) |
|||
{ |
|||
if ( dp->hand.undergun == player && dp->hand.userinput_starttime != 0 ) |
|||
return((int32_t)(dp->hand.userinput_starttime + PANGEA_USERTIMEOUT - time(NULL))); |
|||
else return(-1); |
|||
} |
|||
|
|||
cJSON *pangea_tablestatus(struct pangea_info *sp) |
|||
{ |
|||
uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],totals[CARDS777_MAXPLAYERS],sum; char *handhist; |
|||
int32_t i,n,j,countdown,iter; int64_t total; struct cards777_pubdata *dp; cJSON *bets,*item,*array,*json = cJSON_CreateObject(); |
|||
jadd64bits(json,"tableid",sp->tableid); |
|||
jadd64bits(json,"myslot",sp->myslot); |
|||
jadd64bits(json,"myind",pangea_ind(sp,sp->myslot)); |
|||
dp = sp->dp; |
|||
jaddstr(json,"tablemsig",sp->multisigaddr); |
|||
jaddnum(json,"minbuyin",dp->minbuyin); |
|||
jaddnum(json,"maxbuyin",dp->maxbuyin); |
|||
jaddnum(json,"button",dp->button); |
|||
jaddnum(json,"M",dp->M); |
|||
jaddnum(json,"N",dp->N); |
|||
jaddnum(json,"numcards",dp->numcards); |
|||
jaddnum(json,"numhands",dp->numhands); |
|||
jaddnum(json,"rake",(double)dp->rakemillis/10.); |
|||
jaddnum(json,"maxrake",dstr(dp->maxrake)); |
|||
jaddnum(json,"hostrake",dstr(dp->hostrake)); |
|||
jaddnum(json,"pangearake",dstr(dp->pangearake)); |
|||
jaddnum(json,"bigblind",dstr(dp->bigblind)); |
|||
jaddnum(json,"ante",dstr(dp->ante)); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->N; i++) |
|||
jaddi64bits(array,sp->active[i]); |
|||
jadd(json,"addrs",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->N; i++) |
|||
jaddinum(array,dp->hand.turnis[i]); |
|||
jadd(json,"turns",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<sp->numaddrs; i++) |
|||
jaddinum(array,dstr(sp->balances[i])); |
|||
jadd(json,"balances",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->N; i++) |
|||
jaddinum(array,dstr(dp->hand.snapshot[i])); |
|||
jadd(json,"snapshot",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->N; i++) |
|||
jaddistr(array,pangea_statusstr(dp->hand.betstatus[i])); |
|||
jadd(json,"status",array); |
|||
bets = cJSON_CreateArray(); |
|||
for (total=i=0; i<dp->N; i++) |
|||
{ |
|||
total += dp->hand.bets[i]; |
|||
jaddinum(bets,dstr(dp->hand.bets[i])); |
|||
} |
|||
jadd(json,"bets",bets); |
|||
jaddnum(json,"totalbets",dstr(total)); |
|||
for (iter=0; iter<2; iter++) |
|||
if ( (n= pangea_sidepots(0,sidepots,dp,iter == 0 ? dp->hand.snapshot : dp->hand.bets)) > 0 && n < dp->N ) |
|||
{ |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = cJSON_CreateArray(); |
|||
for (sum=j=0; j<dp->N; j++) |
|||
jaddinum(item,dstr(sidepots[i][j])), sum += sidepots[i][j]; |
|||
totals[i] = sum; |
|||
jaddi(array,item); |
|||
} |
|||
jadd(json,iter == 0 ? "pots" : "RTpots",array); |
|||
item = cJSON_CreateArray(); |
|||
for (sum=i=0; i<n; i++) |
|||
jaddinum(item,dstr(totals[i])), sum += totals[i]; |
|||
jadd(json,iter == 0 ? "potTotals" : "RTpotTotals",item); |
|||
jaddnum(json,iter == 0 ? "sum" : "RTsum",dstr(sum)); |
|||
} |
|||
if ( sp->priv != 0 ) |
|||
{ |
|||
jadd64bits(json,"automuck",sp->priv->automuck); |
|||
jadd64bits(json,"autofold",sp->priv->autofold); |
|||
jadd(json,"hand",pangea_handjson(&dp->hand,sp->priv->hole,sp->isbot[sp->myslot])); |
|||
} |
|||
if ( (handhist= pangea_dispsummary(sp,0,dp->summary,dp->summarysize,sp->tableid,dp->numhands-1,dp->N)) != 0 ) |
|||
{ |
|||
if ( (item= cJSON_Parse(handhist)) != 0 ) |
|||
jadd(json,"actions",item); |
|||
free(handhist); |
|||
} |
|||
if ( (countdown= pangea_countdown(dp,pangea_ind(sp,sp->myslot))) >= 0 ) |
|||
jaddnum(json,"timeleft",countdown); |
|||
if ( dp->hand.finished != 0 ) |
|||
{ |
|||
item = cJSON_CreateObject(); |
|||
jaddnum(item,"hostrake",dstr(dp->hand.hostrake)); |
|||
jaddnum(item,"pangearake",dstr(dp->hand.pangearake)); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->N; i++) |
|||
jaddinum(array,dstr(dp->hand.won[i])); |
|||
jadd(item,"won",array); |
|||
jadd(json,"summary",item); |
|||
} |
|||
return(json); |
|||
} |
|||
|
|||
void pangea_playerprint(struct cards777_pubdata *dp,int32_t i,int32_t myind) |
|||
{ |
|||
int32_t countdown; char str[8]; struct pangea_info *sp = dp->table; |
|||
if ( (countdown= pangea_countdown(dp,i)) >= 0 ) |
|||
sprintf(str,"%2d",countdown); |
|||
else str[0] = 0; |
|||
printf("%d: %6s %12.8f %2s | %12.8f %s\n",i,pangea_statusstr(dp->hand.betstatus[i]),dstr(dp->hand.bets[i]),str,dstr(sp->balances[pangea_slot(sp,i)]),i == myind ? "<<<<<<<<<<<": ""); |
|||
} |
|||
|
|||
void pangea_statusprint(struct cards777_pubdata *dp,struct cards777_privdata *priv,int32_t myind) |
|||
{ |
|||
int32_t i; char handstr[64]; uint8_t hand[7]; |
|||
for (i=0; i<dp->N; i++) |
|||
pangea_playerprint(dp,i,myind); |
|||
handstr[0] = 0; |
|||
if ( dp->hand.community[0] != dp->hand.community[1] ) |
|||
{ |
|||
for (i=0; i<5; i++) |
|||
if ( (hand[i]= dp->hand.community[i]) == 0xff ) |
|||
break; |
|||
if ( i == 5 ) |
|||
{ |
|||
if ( (hand[5]= priv->hole[0]) != 0xff && (hand[6]= priv->hole[1]) != 0xff ) |
|||
set_handstr(handstr,hand,1); |
|||
} |
|||
} |
|||
printf("%s\n",handstr); |
|||
} |
|||
|
|||
/*
|
|||
if ( hn->server->H.slot == 0 ) |
|||
{ |
|||
char *pangea_cashout(char *coinstr,int32_t oldtx_format,uint64_t values[],char *txidstrs[],int32_t vouts[],int32_t numinputs,char *destaddrs[],char *destscripts[],uint64_t outputs[],int32_t n,char *scriptPubKey,char *redeemScript,char *wip,uint64_t txfee,char sigs[][256],int32_t numplayers,uint8_t *privkey,int32_t privkeyind,char *othersignedtx); |
|||
uint64_t values[1],txfee; char *othersignedtx,*rawtx,*txidstrs[1],*destaddrs[1],*destscripts[1],sigs[CARDS777_MAXPLAYERS][256]; int32_t vouts[1]; uint64_t outputs[1]; |
|||
if ( strcmp(dp->coinstr,"BTC") == 0 ) |
|||
{ |
|||
txfee = SATOSHIDEN/10000; |
|||
values[0] = SATOSHIDEN / 5000, txidstrs[0] = "94cb2925d802c6c3695f0765767d892e13bd90ca256cc08ed5d85fd737bcc848", vouts[0] = 0; |
|||
outputs[0] = SATOSHIDEN / 5000 - txfee; |
|||
} |
|||
else |
|||
{ |
|||
txfee = SATOSHIDEN/1000; |
|||
values[0] = SATOSHIDEN, txidstrs[0] = "af980e0cf15c028d571767935e9e78ff0ad3068ff1a2ae2ca62c723a75ed8a80", vouts[0] = 1; |
|||
outputs[0] = SATOSHIDEN - txfee; |
|||
} |
|||
destaddrs[0] = dp->multisigaddr, destscripts[0] = dp->scriptPubKey; |
|||
memset(sigs,0,sizeof(sigs)); |
|||
othersignedtx = 0; |
|||
for (i=0; i<dp->N; i++) |
|||
{ |
|||
rawtx = pangea_cashout(dp->coinstr,strcmp(dp->coinstr,"BTC") == 0,values,txidstrs,vouts,1,destaddrs,destscripts,outputs,1,dp->scriptPubKey,dp->redeemScript,priv->wipstr,txfee,sigs,dp->N,THREADS[i]->hn.client->H.privkey.bytes,i,othersignedtx); |
|||
if ( othersignedtx != 0 ) |
|||
free(othersignedtx); |
|||
othersignedtx = rawtx; |
|||
} |
|||
} |
|||
*/ |
@ -0,0 +1,487 @@ |
|||
/******************************************************************************
|
|||
* 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_buyins(uint32_t *minbuyinp,uint32_t *maxbuyinp) |
|||
{ |
|||
if ( *minbuyinp == 0 && *maxbuyinp == 0 ) |
|||
{ |
|||
*minbuyinp = 100; |
|||
*maxbuyinp = 1000; |
|||
} |
|||
else |
|||
{ |
|||
PNACL_message("minbuyin.%d maxbuyin.%d -> ",*minbuyinp,*maxbuyinp); |
|||
if ( *minbuyinp < 20 ) |
|||
*minbuyinp = 20; |
|||
if ( *maxbuyinp < *minbuyinp ) |
|||
*maxbuyinp = (*minbuyinp * 4); |
|||
if ( *maxbuyinp > 1000 ) |
|||
*maxbuyinp = 1000; |
|||
if ( *minbuyinp > *maxbuyinp ) |
|||
*minbuyinp = *maxbuyinp; |
|||
PNACL_message("(%d %d)\n",*minbuyinp,*maxbuyinp); |
|||
} |
|||
} |
|||
|
|||
struct pangea_info *pangea_create(struct pangea_thread *tp,int32_t *createdflagp,char *base,uint32_t timestamp,uint64_t *addrs,int32_t numaddrs,uint64_t bigblind,uint64_t ante,uint64_t *isbot,uint32_t minbuyin,uint32_t maxbuyin,int32_t hostrake) |
|||
{ |
|||
struct pangea_info *sp = 0; bits256 hash; int32_t i,j,numcards,firstslot = -1; struct cards777_privdata *priv; struct cards777_pubdata *dp; struct iguana_info *coin; |
|||
if ( createdflagp != 0 ) |
|||
*createdflagp = 0; |
|||
for (i=0; i<numaddrs; i++) |
|||
PNACL_message("%llu ",(long long)addrs[i]); |
|||
PNACL_message("pangea_create numaddrs.%d\n",numaddrs); |
|||
for (i=0; i<numaddrs; i++) |
|||
{ |
|||
if ( addrs[i] == tp->nxt64bits ) |
|||
break; |
|||
} |
|||
if ( i == numaddrs ) |
|||
{ |
|||
PNACL_message("this node not in addrs\n"); |
|||
return(0); |
|||
} |
|||
if ( numaddrs > 0 && (sp= calloc(1,sizeof(*sp))) != 0 ) |
|||
{ |
|||
sp->tp = tp; |
|||
numcards = CARDS777_MAXCARDS; |
|||
pangea_buyins(&minbuyin,&maxbuyin); |
|||
tp->numcards = numcards, tp->N = numaddrs; |
|||
sp->numactive = numaddrs; |
|||
sp->dp = dp = cards777_allocpub((numaddrs >> 1) + 1,numcards,numaddrs); |
|||
dp->minbuyin = minbuyin, dp->maxbuyin = maxbuyin; |
|||
sp->minbuyin = minbuyin, sp->maxbuyin = maxbuyin; |
|||
dp->rakemillis = hostrake; |
|||
if ( dp->rakemillis > PANGEA_MAX_HOSTRAKE ) |
|||
dp->rakemillis = PANGEA_MAX_HOSTRAKE; |
|||
dp->rakemillis += PANGEA_MINRAKE_MILLIS; |
|||
if ( dp == 0 ) |
|||
{ |
|||
PNACL_message("pangea_create: unexpected out of memory pub\n"); |
|||
return(0); |
|||
} |
|||
for (j=0; j<5; j++) |
|||
dp->hand.community[j] = 0xff; |
|||
memcpy(sp->addrs,addrs,numaddrs * sizeof(sp->addrs[0])); |
|||
for (j=0; j<numaddrs; j++) |
|||
{ |
|||
//if ( balances != 0 )
|
|||
// dp->balances[j] = balances[j];
|
|||
//else dp->balances[j] = 100;
|
|||
if ( isbot != 0 ) |
|||
sp->isbot[j] = isbot[j]; |
|||
sp->active[j] = addrs[j]; |
|||
} |
|||
sp->priv = priv = cards777_allocpriv(numcards,numaddrs); |
|||
priv->hole[0] = priv->hole[1] = 0xff; |
|||
if ( priv == 0 ) |
|||
{ |
|||
PNACL_message("pangea_create: unexpected out of memory priv\n"); |
|||
return(0); |
|||
} |
|||
priv->automuck = Showmode; |
|||
priv->autofold = Autofold; |
|||
btc_priv2pub(sp->btcpub,tp->hn.client->H.privkey.bytes); |
|||
init_hexbytes_noT(sp->btcpubkeystr,sp->btcpub,33); |
|||
strcpy(sp->coinstr,base); |
|||
strcpy(dp->coinstr,base); |
|||
if ( (coin= iguana_coinfind(base)) != 0 ) |
|||
{ |
|||
sp->addrtype = coin->chain->pubval;//coin777_addrtype(&sp->p2shtype,base);
|
|||
sp->wiftype = coin->chain->wipval;//coin777_wiftype(base);
|
|||
} |
|||
btc_priv2wip(sp->wipstr,tp->hn.client->H.privkey.bytes,sp->wiftype); |
|||
strcpy(sp->btcpubkeys[sp->myslot],sp->btcpubkeystr); |
|||
PNACL_message("T%d: Automuck.%d Autofold.%d rakemillis.%d btcpubkey.(%s) (%s) addrtype.%02x p2sh.%02x wif.%02x\n",tp->hn.client->H.slot,priv->automuck,priv->autofold,dp->rakemillis,sp->btcpubkeystr,dp->coinstr,sp->addrtype,sp->p2shtype,sp->wiftype); |
|||
if ( (sp->timestamp= timestamp) == 0 ) |
|||
sp->timestamp = (uint32_t)time(NULL); |
|||
sp->numaddrs = sp->numactive = numaddrs; |
|||
sp->basebits = stringbits(base); |
|||
sp->bigblind = dp->bigblind = bigblind, sp->ante = dp->ante = ante; |
|||
vcalc_sha256(0,hash.bytes,(uint8_t *)sp,numaddrs * sizeof(sp->addrs[0]) + 4*sizeof(uint32_t) + 3*sizeof(uint64_t)); |
|||
sp->tableid = hash.txid; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
{ |
|||
if ( TABLES[i] != 0 ) |
|||
{ |
|||
if ( sp->tableid == TABLES[i]->tableid && tp->threadid == TABLES[i]->tp->threadid ) |
|||
{ |
|||
PNACL_message("tableid %llu already exists!\n",(long long)sp->tableid); |
|||
free(sp); |
|||
return(TABLES[i]); |
|||
} |
|||
} |
|||
else if ( firstslot < 0 ) |
|||
firstslot = i; |
|||
} |
|||
TABLES[firstslot] = sp; |
|||
if ( createdflagp != 0 ) |
|||
*createdflagp = 1; |
|||
} |
|||
return(sp); |
|||
} |
|||
|
|||
cJSON *pangea_ciphersjson(struct cards777_pubdata *dp,struct cards777_privdata *priv) |
|||
{ |
|||
int32_t i,j,nonz = 0; char hexstr[65]; cJSON *array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->numcards; i++) |
|||
for (j=0; j<dp->N; j++,nonz++) |
|||
{ |
|||
init_hexbytes_noT(hexstr,priv->outcards[nonz].bytes,sizeof(bits256)); |
|||
jaddistr(array,hexstr); |
|||
} |
|||
return(array); |
|||
} |
|||
|
|||
cJSON *pangea_playerpubs(bits256 *playerpubs,int32_t num) |
|||
{ |
|||
int32_t i; char hexstr[65]; cJSON *array = cJSON_CreateArray(); |
|||
for (i=0; i<num; i++) |
|||
{ |
|||
init_hexbytes_noT(hexstr,playerpubs[i].bytes,sizeof(bits256)); |
|||
//PNACL_message("(%llx-> %s) ",(long long)playerpubs[i].txid,hexstr);
|
|||
jaddistr(array,hexstr); |
|||
} |
|||
//PNACL_message("playerpubs\n");
|
|||
return(array); |
|||
} |
|||
|
|||
cJSON *pangea_cardpubs(struct cards777_pubdata *dp) |
|||
{ |
|||
int32_t i; char hexstr[65]; cJSON *array = cJSON_CreateArray(); |
|||
for (i=0; i<dp->numcards; i++) |
|||
{ |
|||
init_hexbytes_noT(hexstr,dp->hand.cardpubs[i].bytes,sizeof(bits256)); |
|||
jaddistr(array,hexstr); |
|||
} |
|||
init_hexbytes_noT(hexstr,dp->hand.checkprod.bytes,sizeof(bits256)); |
|||
jaddistr(array,hexstr); |
|||
return(array); |
|||
} |
|||
|
|||
cJSON *pangea_sharenrs(uint8_t *sharenrs,int32_t n) |
|||
{ |
|||
int32_t i; cJSON *array = cJSON_CreateArray(); |
|||
for (i=0; i<n; i++) |
|||
jaddinum(array,sharenrs[i]); |
|||
return(array); |
|||
} |
|||
|
|||
char *pangea_newtable(int32_t threadid,cJSON *json,uint64_t my64bits,bits256 privkey,bits256 pubkey,char *transport,char *ipaddr,uint16_t port,uint32_t minbuyin,uint32_t maxbuyin,int32_t hostrake) |
|||
{ |
|||
int32_t createdflag,num,i,myind= -1; uint64_t tableid,addrs[CARDS777_MAXPLAYERS],isbot[CARDS777_MAXPLAYERS]; |
|||
struct pangea_info *sp; cJSON *array; struct pangea_thread *tp=0; char *base,*str,*hexstr,*endpoint,hex[1024]; uint32_t timestamp; |
|||
struct cards777_pubdata *dp; struct pangeanet777_server *srv=0; |
|||
str = jprint(json,0); |
|||
PNACL_message("T%d NEWTABLE.(%s)\n",threadid,str); |
|||
free(str); |
|||
if ( (tableid= j64bits(json,"tableid")) != 0 && (base= jstr(json,"base")) != 0 && (timestamp= juint(json,"timestamp")) != 0 ) |
|||
{ |
|||
if ( (array= jarray(&num,json,"addrs")) == 0 || num < 2 || num > CARDS777_MAXPLAYERS ) |
|||
{ |
|||
PNACL_message("no address or illegal num.%d\n",num); |
|||
return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}")); |
|||
} |
|||
for (i=0; i<num; i++) |
|||
{ |
|||
addrs[i] = j64bits(jitem(array,i),0); |
|||
if ( addrs[i] == my64bits ) |
|||
{ |
|||
threadid = myind = i; |
|||
if ( (tp= THREADS[threadid]) == 0 ) |
|||
{ |
|||
THREADS[threadid] = tp = calloc(1,sizeof(*THREADS[threadid])); |
|||
if ( i == 0 ) |
|||
{ |
|||
if ( (srv= pangeanet777_server(privkey,pubkey,transport,ipaddr,port,num)) == 0 ) |
|||
PNACL_message("cant create pangeanet777 server\n"); |
|||
else |
|||
{ |
|||
tp->hn.server = srv; |
|||
memcpy(srv->H.privkey.bytes,privkey.bytes,sizeof(bits256)); |
|||
memcpy(srv->H.pubkey.bytes,pubkey.bytes,sizeof(bits256)); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
PANGEA_MAXTHREADS = 1; |
|||
if ( (endpoint= jstr(json,"pangea_endpoint")) != 0 ) |
|||
{ |
|||
if ( strncmp(endpoint,"tcp://127.0.0.1",strlen("tcp://127.0.0.1")) == 0 || strncmp(endpoint,"ws://127.0.0.1",strlen("ws://127.0.0.1")) == 0 ) |
|||
{ |
|||
PNACL_message("ILLEGAL pangea_endpoint.(%s)\n",endpoint); |
|||
return(clonestr("{\"error\":\"contact pangea host and tell them to add myipaddr to their SuperNET.conf\"}")); |
|||
} |
|||
if ( (tp->hn.client= pangeanet777_client(privkey,pubkey,endpoint,i)) == 0 ) |
|||
{ |
|||
memcpy(tp->hn.client->H.privkey.bytes,privkey.bytes,sizeof(bits256)); |
|||
memcpy(tp->hn.client->H.pubkey.bytes,pubkey.bytes,sizeof(bits256)); |
|||
} |
|||
} |
|||
} |
|||
tp->nxt64bits = my64bits; |
|||
} |
|||
} |
|||
} |
|||
if ( myind < 0 ) |
|||
return(clonestr("{\"error\":\"this table is not for me\"}")); |
|||
/*if ( (array= jarray(&num,json,"balances")) == 0 )
|
|||
{ |
|||
PNACL_message("no balances or illegal num.%d\n",num); |
|||
return(clonestr("{\"error\":\"no balances or illegal numplayers\"}")); |
|||
} |
|||
for (i=0; i<num; i++) |
|||
balances[i] = j64bits(jitem(array,i),0);*/ |
|||
if ( (array= jarray(&num,json,"isbot")) != 0 ) |
|||
{ |
|||
for (i=0; i<num; i++) |
|||
isbot[i] = j64bits(jitem(array,i),0); |
|||
} |
|||
else memset(isbot,0,sizeof(isbot)); |
|||
PNACL_message("call pangea_create\n"); |
|||
if ( (sp= pangea_create(tp,&createdflag,base,timestamp,addrs,num,j64bits(json,"bigblind"),j64bits(json,"ante"),isbot,minbuyin,maxbuyin,hostrake)) == 0 ) |
|||
{ |
|||
PNACL_message("cant create table.(%s) numaddrs.%d\n",base,num); |
|||
return(clonestr("{\"error\":\"cant create table\"}")); |
|||
} |
|||
PNACL_message("back from pangea_create\n"); |
|||
dp = sp->dp; sp->myslot = sp->myind = myind; |
|||
dp->table = sp; |
|||
tp->numcards = dp->numcards, tp->N = dp->N, tp->M = dp->M; |
|||
if ( threadid == 0 ) |
|||
{ |
|||
tp->hn.server->clients[0].pubdata = dp; |
|||
tp->hn.server->clients[0].privdata = sp->priv; |
|||
tp->hn.server->H.pubdata = dp; |
|||
tp->hn.server->H.privdata = sp->priv; |
|||
} |
|||
else |
|||
{ |
|||
tp->hn.client->my.pubdata = dp; |
|||
tp->hn.client->my.privdata = sp->priv; |
|||
tp->hn.client->H.pubdata = dp; |
|||
tp->hn.client->H.privdata = sp->priv; |
|||
if ( THREADS[0] != 0 ) |
|||
{ |
|||
THREADS[0]->hn.server->clients[threadid].pubdata = dp; |
|||
THREADS[0]->hn.server->clients[threadid].privdata = sp->priv; |
|||
} |
|||
} |
|||
if ( (array= jarray(&num,json,"playerpubs")) == 0 || num < 2 || num > CARDS777_MAXPLAYERS ) |
|||
{ |
|||
PNACL_message("no address or illegal num.%d\n",num); |
|||
return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}")); |
|||
} |
|||
for (i=0; i<num; i++) |
|||
{ |
|||
hexstr = jstr(jitem(array,i),0); |
|||
decode_hex(sp->playerpubs[i].bytes,sizeof(bits256),hexstr); |
|||
PNACL_message("set playerpubs.(%s) %llx\n",hexstr,(long long)sp->playerpubs[i].txid); |
|||
if ( sp->playerpubs[i].txid == 0 ) |
|||
{ |
|||
PNACL_message("player.%d has no NXT pubkey\n",i); |
|||
return(clonestr("{\"error\":\"not all players have published NXT pubkeys\"}")); |
|||
} |
|||
} |
|||
if ( myind >= 0 && createdflag != 0 && addrs[myind] == tp->nxt64bits ) |
|||
{ |
|||
memcpy(sp->addrs,addrs,sizeof(*addrs) * dp->N); |
|||
dp->readymask |= (1 << sp->myslot); |
|||
pangea_sendcmd(hex,&tp->hn,"ready",-1,sp->btcpub,sizeof(sp->btcpub),0,0); |
|||
return(clonestr("{\"result\":\"newtable created\"}")); |
|||
} |
|||
else if ( createdflag == 0 ) |
|||
{ |
|||
if ( sp->addrs[0] == tp->nxt64bits ) |
|||
return(clonestr("{\"result\":\"this is my table\"}")); |
|||
else return(clonestr("{\"result\":\"table already exists\"}")); |
|||
} |
|||
} |
|||
return(clonestr("{\"error\":\"no tableid\"}")); |
|||
} |
|||
|
|||
struct pangea_thread *pangea_threadinit(struct supernet_info *plugin,int32_t maxplayers) |
|||
{ |
|||
/* struct pangea_thread *tp; struct pangeanet777_server *srv;
|
|||
PANGEA_MAXTHREADS = 1; |
|||
THREADS[0] = tp = calloc(1,sizeof(*THREADS[0])); |
|||
if ( tp == 0 ) |
|||
{ |
|||
PNACL_message("pangea_threadinit: unexpected out of memory\n"); |
|||
return(0); |
|||
} |
|||
tp->nxt64bits = plugin->nxt64bits; |
|||
if ( (srv= pangeanet777_server(*(bits256 *)plugin->mypriv,*(bits256 *)plugin->mypub,plugin->transport,plugin->ipaddr,plugin->pangeaport,9)) == 0 ) |
|||
PNACL_message("cant create pangeanet777 server\n"); |
|||
else |
|||
{ |
|||
tp->hn.server = srv; |
|||
memcpy(srv->H.privkey.bytes,plugin->mypriv,sizeof(bits256)); |
|||
memcpy(srv->H.pubkey.bytes,plugin->mypub,sizeof(bits256)); |
|||
} |
|||
return(tp);*/ |
|||
return(0); |
|||
} |
|||
|
|||
void pangea_create_newtable(char *retbuf,struct pangea_info *sp,struct cards777_pubdata *dp,uint64_t *isbot) |
|||
{ |
|||
char *addrstr,*ciphers,*playerpubs,*isbotstr; |
|||
isbotstr = jprint(addrs_jsonarray(isbot,dp->N),1); |
|||
//balancestr = jprint(addrs_jsonarray(balances,num),1);
|
|||
addrstr = jprint(addrs_jsonarray(sp->addrs,dp->N),1); |
|||
ciphers = jprint(pangea_ciphersjson(dp,sp->priv),1); |
|||
playerpubs = jprint(pangea_playerpubs(sp->playerpubs,dp->N),1); |
|||
dp->readymask |= (1 << sp->myslot); |
|||
sprintf(retbuf,"{\"cmd\":\"newtable\",\"broadcast\":\"allnodes\",\"myind\":%d,\"pangea_endpoint\":\"%s\",\"plugin\":\"relay\",\"destplugin\":\"pangea\",\"method\":\"busdata\",\"submethod\":\"newtable\",\"my64bits\":\"%llu\",\"tableid\":\"%llu\",\"timestamp\":%u,\"M\":%d,\"N\":%d,\"base\":\"%s\",\"bigblind\":\"%llu\",\"minbuyin\":\"%d\",\"maxbuyin\":\"%u\",\"rakemillis\":\"%u\",\"ante\":\"%llu\",\"playerpubs\":%s,\"addrs\":%s,\"isbot\":%s}",sp->myslot,sp->tp->hn.server->ep.endpoint,(long long)sp->tp->nxt64bits,(long long)sp->tableid,sp->timestamp,dp->M,dp->N,sp->coinstr,(long long)sp->bigblind,dp->minbuyin,dp->maxbuyin,dp->rakemillis,(long long)sp->ante,playerpubs,addrstr,isbotstr); //\"pluginrequest\":\"SuperNET\",
|
|||
PNACL_message("START.(%s)\n",retbuf); |
|||
//dp->pmworks |= (1 << sp->myind);
|
|||
free(addrstr), free(ciphers), free(playerpubs), free(isbotstr);// free(balancestr);
|
|||
} |
|||
|
|||
int32_t pangea_start(struct supernet_info *plugin,char *retbuf,char *base,uint32_t timestamp,uint64_t bigblind,uint64_t ante,int32_t hostrake,int32_t maxplayers,uint32_t minbuyin,uint32_t maxbuyin,cJSON *json) |
|||
{ |
|||
char destNXT[64]; struct pangea_thread *tp; struct cards777_pubdata *dp; |
|||
int32_t createdflag,addrtype,haspubkey,i,j,slot,n,myind=-1,r,num=0,threadid=0; uint64_t addrs[512],isbot[512],tmp; |
|||
struct pangea_info *sp; cJSON *bids,*walletitem,*item; struct iguana_info *coin; |
|||
memset(addrs,0,sizeof(addrs)); |
|||
PNACL_message("pangea_start rakemillis.%d\n",hostrake); |
|||
//memset(balances,0,sizeof(balances));
|
|||
pangea_buyins(&minbuyin,&maxbuyin); |
|||
if ( hostrake < 0 || hostrake > PANGEA_MAX_HOSTRAKE ) |
|||
{ |
|||
PNACL_message("illegal hostrake.%d\n",hostrake); |
|||
strcpy(retbuf,"{\"error\":\"illegal hostrake\"}"); |
|||
return(-1); |
|||
} |
|||
if ( bigblind == 0 ) |
|||
bigblind = SATOSHIDEN; |
|||
if ( (tp= THREADS[threadid]) == 0 ) |
|||
{ |
|||
pangea_threadinit(plugin,maxplayers); |
|||
if ( (tp=THREADS[0]) == 0 ) |
|||
{ |
|||
strcpy(retbuf,"{\"error\":\"uinitialized threadid\"}"); |
|||
PNACL_message("%s\n",retbuf); |
|||
return(-1); |
|||
} |
|||
} |
|||
PNACL_message("mynxt64bits.%llu base.(%s) maxplayers.%d minbuyin.%u maxbuyin.%u\n",(long long)tp->nxt64bits,base,maxplayers,minbuyin,maxbuyin); |
|||
if ( base == 0 || base[0] == 0 || maxplayers < 2 || maxplayers > CARDS777_MAXPLAYERS ) |
|||
{ |
|||
sprintf(retbuf,"{\"error\":\"bad params\"}"); |
|||
PNACL_message("%s\n",retbuf); |
|||
return(-1); |
|||
} |
|||
if ( (coin= iguana_coinfind(base)) != 0 ) |
|||
addrtype = coin->chain->pubval;//coin777_addrtype(&p2shtype,base);
|
|||
if ( (bids= jarray(&n,json,"bids")) != 0 ) |
|||
{ |
|||
PNACL_message("numbids.%d\n",n); |
|||
for (i=num=0; i<n; i++) |
|||
{ |
|||
item = jitem(bids,i); |
|||
if ( (addrs[num]= j64bits(item,"offerNXT")) != 0 && (walletitem= jobj(item,"wallet")) != 0 ) |
|||
{ |
|||
if ( j64bits(walletitem,"bigblind") == bigblind && j64bits(walletitem,"ante") == ante && juint(walletitem,"rakemillis") == hostrake ) |
|||
{ |
|||
//balances[num] = j64bits(walletitem,"balance");
|
|||
isbot[num] = juint(walletitem,"isbot"); |
|||
PNACL_message("(i.%d %llu) ",i,(long long)addrs[num]);//,dstr(balances[num]));
|
|||
for (j=0; j<num; j++) |
|||
if ( addrs[j] == addrs[num] ) |
|||
break; |
|||
if ( j == num ) |
|||
{ |
|||
if ( addrs[num] == tp->nxt64bits ) |
|||
myind = num; |
|||
PNACL_message("%llu ",(long long)addrs[num]); |
|||
num++; |
|||
} |
|||
} |
|||
else PNACL_message("%d: %llu mismatched walletitem bigblind %.8f ante %.8f rake %.1f%%\n",i,(long long)addrs[num],dstr(j64bits(walletitem,"bigblind")),dstr(j64bits(walletitem,"ante")),(double)juint(walletitem,"rakemillis")/10.); |
|||
} |
|||
} |
|||
} |
|||
PNACL_message("(%llu) pangea_start(%s) threadid.%d myind.%d num.%d maxplayers.%d\n",(long long)tp->nxt64bits,base,tp->threadid,myind,num,maxplayers); |
|||
if ( (i= myind) > 0 ) |
|||
{ |
|||
addrs[i] = addrs[0]; |
|||
addrs[0] = tp->nxt64bits; |
|||
//tmp = balances[i];
|
|||
//balances[i] = balances[0];
|
|||
//balances[0] = tmp;
|
|||
tmp = isbot[i]; |
|||
isbot[i] = isbot[0]; |
|||
isbot[0] = tmp; |
|||
i = 0; |
|||
strcpy(retbuf,"{\"error\":\"host needs to be locally started and the first entry in addrs\"}"); |
|||
return(-1); |
|||
} |
|||
while ( num > maxplayers ) |
|||
{ |
|||
r = (rand() % (num-1)); |
|||
PNACL_message("swap out %d of %d\n",r+1,num); |
|||
num--; |
|||
isbot[r + 1] = isbot[num]; |
|||
//balances[r + 1] = balances[num];
|
|||
addrs[r + 1] = addrs[num]; |
|||
} |
|||
PNACL_message("pangea numplayers.%d\n",num); |
|||
if ( (sp= pangea_create(tp,&createdflag,base,timestamp,addrs,num,bigblind,ante,isbot,minbuyin,maxbuyin,hostrake)) == 0 ) |
|||
{ |
|||
PNACL_message("cant create table.(%s) numaddrs.%d\n",base,num); |
|||
strcpy(retbuf,"{\"error\":\"cant create table, make sure all players have published NXT pubkeys\"}"); |
|||
return(-1); |
|||
} |
|||
PNACL_message("back from pangea_create\n"); |
|||
dp = sp->dp, dp->table = sp; |
|||
sp->myslot = sp->myind = myind; |
|||
if ( createdflag != 0 && myind == 0 && addrs[myind] == tp->nxt64bits ) |
|||
{ |
|||
tp->numcards = dp->numcards, tp->N = dp->N, tp->M = dp->M; |
|||
PNACL_message("myind.%d: hostrake.%d\n",myind,dp->rakemillis); |
|||
dp->minbuyin = minbuyin, dp->maxbuyin = maxbuyin; |
|||
tp->hn.server->clients[myind].pubdata = dp; |
|||
tp->hn.server->clients[myind].privdata = sp->priv; |
|||
tp->hn.server->H.pubdata = dp; |
|||
tp->hn.server->H.privdata = sp->priv; |
|||
for (j=0; j<dp->N; j++) |
|||
{ |
|||
if ( THREADS[j] != 0 ) |
|||
sp->playerpubs[j] = THREADS[j]->hn.client->H.pubkey; |
|||
else |
|||
{ |
|||
expand_nxt64bits(destNXT,addrs[j]); |
|||
sp->playerpubs[j] = issue_getpubkey(&haspubkey,destNXT); |
|||
if ( (slot= pangeanet777_register(THREADS[0]->hn.server,sp->playerpubs[j],-1)) != j ) |
|||
PNACL_message("unexpected register slot.%d for j.%d\n",slot,j); |
|||
} |
|||
//PNACL_message("thread[%d] pub.%llx priv.%llx\n",j,(long long)dp->playerpubs[j].txid,(long long)THREADS[j]->hn.client->H.privkey.txid);
|
|||
} |
|||
pangea_create_newtable(retbuf,sp,dp,isbot); |
|||
#ifdef BUNDLED |
|||
if ( 1 ) |
|||
{ |
|||
char *busdata_sync(uint32_t *noncep,char *jsonstr,char *broadcastmode,char *destNXTaddr); |
|||
char *str; uint32_t nonce; |
|||
if ( (str= busdata_sync(&nonce,retbuf,"allnodes",0)) != 0 ) |
|||
free(str); |
|||
} |
|||
#endif |
|||
} |
|||
return(0); |
|||
} |
@ -0,0 +1,435 @@ |
|||
/******************************************************************************
|
|||
* 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" |
|||
|
|||
struct pangeanet777_id *pangeanet777_find(struct pangeanet777_server *srv,bits256 senderpub) |
|||
{ |
|||
int32_t i; uint64_t senderbits = acct777_nxt64bits(senderpub); |
|||
if ( srv->num > 0 ) |
|||
{ |
|||
for (i=0; i<srv->max; i++) |
|||
if ( srv->clients[i].nxt64bits == senderbits ) |
|||
return(&srv->clients[i]); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
void pangeanet777_lastcontact(struct pangeanet777_server *srv,bits256 senderpub) |
|||
{ |
|||
struct pangeanet777_id *ptr; |
|||
if ( (ptr= pangeanet777_find(srv,senderpub)) != 0 ) |
|||
ptr->lastcontact = (uint32_t)time(NULL); |
|||
} |
|||
|
|||
void pangeanet777_processmsg(uint64_t *destbitsp,bits256 *senderpubp,queue_t *Q,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t origlen,int32_t pmflag) |
|||
{ |
|||
char *jsonstr = 0; bits256 sig; uint32_t timestamp; int32_t len; uint64_t senderbits; uint8_t *ptr=0; cJSON *json; long extra; |
|||
extra = sizeof(*senderpubp) + sizeof(*destbitsp) + sizeof(sig) + sizeof(senderbits) + sizeof(timestamp); |
|||
if ( (len= origlen) > extra ) |
|||
{ |
|||
//printf("got msglen.%d\n",origlen);
|
|||
if ( (ptr= malloc(len*4 + 8192 + sizeof(struct queueitem) - extra)) == 0 ) |
|||
{ |
|||
printf("hostnet777_processmsg cant alloc queueitem\n"); |
|||
return; |
|||
} |
|||
if ( (len= SuperNET_decrypt(senderpubp,&senderbits,×tamp,mypriv,mypub,&ptr[sizeof(struct queueitem)],len*4,msg,len)) > 1 && len < len*4 ) |
|||
{ |
|||
jsonstr = (char *)&ptr[sizeof(struct queueitem)]; |
|||
if ( (json= cJSON_Parse(jsonstr)) != 0 ) |
|||
{ |
|||
//printf("now.%lld vs millitime.%lld lag.%lld\n",(long long)now,(long long)millitime,(long long)(millitime - now));
|
|||
if ( pmflag != 0 && juint(json,"timestamp") != timestamp && juint(json,"timestamp")+1 != timestamp ) |
|||
printf("msg.(%s) timestamp.%u mismatch | now.%ld\n",jsonstr,timestamp,(long)time(NULL)); |
|||
else if ( pmflag != 0 && j64bits(json,"sender") != senderbits ) |
|||
printf("msg.(%ld) sender.%llu mismatch vs json.%llu\n",(long)strlen(jsonstr),(long long)senderbits,(long long)j64bits(json,"sender")); |
|||
else |
|||
{ |
|||
//printf("%llu: QUEUE msg.%d\n",(long long)acct777_nxt64bits(mypub),len);
|
|||
//if ( hostnet777_hashes(recvhashes,64,ptr,len) < 0 )
|
|||
queue_enqueue("host777",Q,(void *)ptr,0); |
|||
ptr = 0; |
|||
} |
|||
free_json(json); |
|||
} else printf("parse error.(%s)\n",jsonstr); |
|||
} else printf("decrypt error len.%d origlen.%d\n",len,origlen); |
|||
} else printf("origlen.%d\n",origlen); |
|||
if ( ptr != 0 ) |
|||
free(ptr); |
|||
} |
|||
|
|||
int32_t pangeanet777_idle(union pangeanet777 *hn) |
|||
{ |
|||
int32_t len,slot,sock,n = 0; bits256 senderpub,mypriv,mypub; uint64_t destbits; uint8_t *msg; |
|||
long extra = sizeof(bits256)+sizeof(uint64_t); |
|||
if ( (slot= hn->client->H.slot) != 0 ) |
|||
{ |
|||
mypriv = hn->client->H.privkey, mypub = hn->client->H.pubkey; |
|||
if ( (sock= hn->client->subsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) |
|||
{ |
|||
SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); |
|||
//printf("client got pub len.%d\n",len);
|
|||
if ( destbits == 0 || destbits == hn->client->H.nxt64bits ) |
|||
pangeanet777_processmsg(&destbits,&senderpub,&hn->client->H.Q,mypriv,mypub,msg,len,0), n++; |
|||
nn_freemsg(msg); |
|||
} else if ( hn->client->H.pollfunc != 0 ) |
|||
(*hn->client->H.pollfunc)(hn); |
|||
} |
|||
else |
|||
{ |
|||
//printf("server idle %.0f\n",milliseconds());
|
|||
mypriv = hn->server->H.privkey, mypub = hn->server->H.pubkey; |
|||
for (slot=1; slot<hn->server->num; slot++) |
|||
{ |
|||
//printf("check ind.%d %.0f\n",ind,milliseconds());
|
|||
if ( (sock= hn->server->clients[slot].pmsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) |
|||
{ |
|||
//printf("server got pm[%d] %d\n",slot,len);
|
|||
SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); |
|||
if ( destbits == 0 || destbits == hn->server->H.nxt64bits ) |
|||
{ |
|||
pangeanet777_processmsg(&destbits,&senderpub,&hn->server->H.Q,mypriv,mypub,msg,len,1); |
|||
pangeanet777_lastcontact(hn->server,senderpub); |
|||
} |
|||
printf("pangeanet777_idle: do the send here\n"); |
|||
//pangeanet777_send(hn->server->pubsock,msg,len);
|
|||
nn_freemsg(msg); |
|||
} |
|||
} |
|||
if ( hn->server->H.pollfunc != 0 ) |
|||
(*hn->server->H.pollfunc)(hn); |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
int32_t pangeanet777_replace(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot) |
|||
{ |
|||
char endpoint[128],buf[128]; uint64_t nxt64bits = acct777_nxt64bits(clientpub); |
|||
sprintf(endpoint,"%s://%s:%u",srv->ep.transport,srv->ep.ipaddr,srv->ep.port + slot + 1); |
|||
//sprintf(buf,"%s://127.0.0.1:%u",srv->ep.transport,srv->ep.port + slot + 1);
|
|||
strcpy(buf,endpoint); |
|||
if ( srv->clients[slot].pmsock < 0 ) |
|||
{ |
|||
printf("pangeanet777_replace deal with getting new socket here\n"); |
|||
//srv->clients[slot].pmsock = nn_createsocket(buf,1,"NN_PULL",NN_PULL,srv->ep.port + slot + 1,10,10);
|
|||
} |
|||
printf("NN_PULL.%d for slot.%d\n",srv->clients[slot].pmsock,slot); |
|||
srv->clients[slot].pubkey = clientpub; |
|||
srv->clients[slot].nxt64bits = nxt64bits; |
|||
srv->clients[slot].lastcontact = (uint32_t)time(NULL); |
|||
return(srv->clients[slot].pmsock); |
|||
} |
|||
|
|||
int32_t pangeanet777_register(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot) |
|||
{ |
|||
int32_t i,n; struct pangeanet777_id *ptr; |
|||
if ( slot < 0 ) |
|||
{ |
|||
if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 ) |
|||
{ |
|||
slot = (int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients)); |
|||
//printf("pangea_register: deregister slot.%d\n",slot);
|
|||
if ( ptr->pmsock >= 0 ) |
|||
nn_shutdown(ptr->pmsock,0); |
|||
memset(ptr,0,sizeof(*ptr)); |
|||
ptr->pmsock = -1; |
|||
srv->num--; |
|||
return(-1); |
|||
} |
|||
for (slot=1; slot<srv->max; slot++) |
|||
if ( srv->clients[slot].nxt64bits == 0 ) |
|||
break; |
|||
} |
|||
if ( srv->num >= srv->max ) |
|||
{ |
|||
printf("pangea_register: cant register anymore num.%d vs max.%d\n",srv->num,srv->max); |
|||
return(-1); |
|||
} |
|||
if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 ) |
|||
{ |
|||
printf("pangea_register: cant register duplicate %llu\n",(long long)acct777_nxt64bits(clientpub)); |
|||
return((int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients))); |
|||
} |
|||
if ( slot != srv->num ) |
|||
{ |
|||
printf("pangea_register: cant register slot.%d vs num.%d vs max.%d\n",slot,srv->num,srv->max); |
|||
return(-1); |
|||
} |
|||
pangeanet777_replace(srv,clientpub,slot); |
|||
srv->num++; |
|||
for (i=n=0; i<srv->max; i++) |
|||
if ( srv->clients[i].nxt64bits != 0 ) |
|||
n++; |
|||
if ( n != srv->num ) |
|||
{ |
|||
printf("mismatched nonz nxt64bits n.%d vs %d\n",n,srv->num); |
|||
srv->num = n; |
|||
} |
|||
return(slot); |
|||
} |
|||
|
|||
struct pangeanet777_client *pangeanet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot) |
|||
{ |
|||
char endbuf[128],endbuf2[128]; uint16_t port; struct pangeanet777_client *ptr; |
|||
ptr = calloc(1,sizeof(*ptr)); |
|||
ptr->H.slot = slot; |
|||
ptr->H.privkey = privkey, ptr->H.pubkey = ptr->my.pubkey = pubkey; |
|||
ptr->H.nxt64bits = ptr->my.nxt64bits = acct777_nxt64bits(pubkey); |
|||
ptr->my.lastcontact = (uint32_t)time(NULL); |
|||
strcpy(endbuf,srvendpoint); |
|||
endbuf[strlen(endbuf)-4] = 0; |
|||
port = atoi(&srvendpoint[strlen(endbuf)]); |
|||
sprintf(endbuf2,"%s%u",endbuf,port + 1 + slot); |
|||
printf("pangeanet777_client: deal with creating connections here\n"); |
|||
//ptr->my.pmsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,100);
|
|||
printf("NN_PUSH %d from (%s) port.%d\n",ptr->my.pmsock,endbuf2,port+1+slot); |
|||
sprintf(endbuf2,"%s%u",endbuf,port); |
|||
//ptr->subsock = nn_createsocket(endbuf2,0,"NN_SUB",NN_SUB,0,10,100);
|
|||
printf("SUB %d from (%s) port.%d\n",ptr->subsock,endbuf2,port); |
|||
nn_setsockopt(ptr->subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); |
|||
//sprintf(endbuf2,"%s%u",endbuf,port);
|
|||
//ptr->pushsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,1);
|
|||
//printf("PUSH %d to (%s)\n",ptr->pushsock,endbuf2);
|
|||
return(ptr); |
|||
} |
|||
|
|||
void pangeanet777_freeclient(struct pangeanet777_client *client) |
|||
{ |
|||
client->H.done = 1; |
|||
if ( client->subsock >= 0 ) |
|||
nn_shutdown(client->subsock,0); |
|||
//if ( client->pushsock >= 0 )
|
|||
// nn_shutdown(client->pushsock,0);
|
|||
if ( client->my.pmsock >= 0 ) |
|||
nn_shutdown(client->my.pmsock,0); |
|||
} |
|||
|
|||
void pangeanet777_freeserver(struct pangeanet777_server *srv) |
|||
{ |
|||
int32_t ind; |
|||
srv->H.done = 1; |
|||
//if ( srv->pullsock >= 0 )
|
|||
// nn_shutdown(srv->pullsock,0);
|
|||
if ( srv->pubsock >= 0 ) |
|||
nn_shutdown(srv->pubsock,0); |
|||
for (ind=1; ind<srv->max; ind++) |
|||
{ |
|||
if ( srv->clients[ind].pmsock >= 0 ) |
|||
nn_shutdown(srv->clients[ind].pmsock,0); |
|||
} |
|||
} |
|||
|
|||
struct pangeanet777_server *pangeanet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients) |
|||
{ |
|||
struct pangeanet777_server *srv; int32_t i; struct pangeanet777_endpoint *ep; char buf[128]; |
|||
srv = calloc(1,sizeof(*srv) + maxclients*sizeof(struct pangeanet777_id)); |
|||
srv->max = maxclients; |
|||
ep = &srv->ep; |
|||
if ( (ep->port= port) == 0 ) |
|||
ep->port = port = 8000 + (rand() % 1000); |
|||
if ( transport == 0 || transport[0] == 0 ) |
|||
transport = TEST_TRANSPORT; |
|||
if ( ipaddr == 0 || ipaddr[0] == 0 ) |
|||
ipaddr = "127.0.0.1"; |
|||
strcpy(ep->transport,transport), strcpy(ep->ipaddr,ipaddr); |
|||
for (i=0; i<maxclients; i++) |
|||
srv->clients[i].pmsock = -1; |
|||
srv->H.privkey = srvprivkey; |
|||
srv->H.pubkey = srv->clients[0].pubkey = srvpubkey; |
|||
srv->H.nxt64bits = srv->clients[0].nxt64bits = acct777_nxt64bits(srvpubkey); |
|||
sprintf(ep->endpoint,"%s://%s:%u",transport,ipaddr,port); |
|||
if ( strcmp(transport,"tcpmux") == 0 ) |
|||
strcat(ep->endpoint,"/pangea"); |
|||
//sprintf(buf,"%s://127.0.0.1:%u",transport,port);
|
|||
strcpy(buf,ep->endpoint); |
|||
printf("pangeanet777_server: create socket here\n"); |
|||
//srv->pubsock = nn_createsocket(buf,1,"NN_PUB",NN_PUB,port,10,100);
|
|||
printf("PUB.%d to (%s) pangeaport.%d\n",srv->pubsock,ep->endpoint,port); |
|||
srv->num = 1; |
|||
return(srv); |
|||
} |
|||
|
|||
void *pangeanet777_idler(union pangeanet777 *ptr) |
|||
{ |
|||
while ( ptr->client->H.done == 0 ) |
|||
{ |
|||
if ( pangeanet777_idle(ptr) == 0 ) |
|||
usleep(1000); |
|||
} |
|||
//printf("pangea_idler ind.%d done\n",ptr->client->H.slot);
|
|||
sleep(1); |
|||
free(ptr); |
|||
return(0); |
|||
} |
|||
|
|||
int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len,uint8_t *data,int32_t delaymillis); |
|||
|
|||
#define pangeanet777_broadcast(mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,mypriv,mypub,msg,len,space,0) |
|||
#define pangeanet777_blindcast(msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,zeropoint,zeropoint,msg,len,space,0) |
|||
#define pangeanet777_signedPM(destpub,mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,mypriv,mypub,msg,len,space,0) |
|||
#define pangeanet777_blindPM(destpub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,zeropoint,zeropoint,msg,len,space,0) |
|||
void pangeanet777_msg(uint64_t destbits,bits256 destpub,union pangeanet777 *src,int32_t blindflag,char *jsonstr,int32_t len) |
|||
{ |
|||
static bits256 zeropoint; |
|||
struct supernet_info *myinfo = SuperNET_MYINFO(0); uint8_t *space; |
|||
struct iguana_peer *addr = 0; struct iguana_info *coin = iguana_coinfind("BTCD"); |
|||
if ( destbits == 0 ) |
|||
{ |
|||
//printf(">>>>>>>>> blind.%d broadcast from %llu, len.%d\n",blindflag,(long long)src->client->H.nxt64bits,len);
|
|||
space = calloc(1,IGUANA_MAXPACKETSIZE); |
|||
if ( blindflag != 0 ) |
|||
pangeanet777_blindcast((uint8_t *)jsonstr,len); |
|||
else pangeanet777_broadcast(src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); |
|||
free(space); |
|||
if ( src->server->H.slot == 0 ) |
|||
queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); |
|||
} |
|||
else if ( destbits != src->client->H.nxt64bits ) |
|||
{ |
|||
//printf(">>>>>>>>> blind.%d PM from %llu to %llu\n",blindflag,(long long)src->client->H.nxt64bits,(long long)destbits);
|
|||
space = calloc(1,IGUANA_MAXPACKETSIZE); |
|||
if ( blindflag != 0 ) |
|||
pangeanet777_blindPM(destpub,(uint8_t *)jsonstr,len); |
|||
else pangeanet777_signedPM(destpub,src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); |
|||
free(space); |
|||
} |
|||
else queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); |
|||
} |
|||
|
|||
int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<sp->numactive; i++) |
|||
if ( sp->active[i] == nxt64bits ) |
|||
return(i); |
|||
for (i=0; i<sp->numactive; i++) |
|||
PNACL_message("%llu ",(long long)sp->active[i]); |
|||
PNACL_message("active[]\n"); |
|||
for (i=0; i<sp->numaddrs; i++) |
|||
PNACL_message("%llu ",(long long)sp->addrs[i]); |
|||
PNACL_message("addrs[]\n"); |
|||
PNACL_message("pangea_search: slot.%d ind.%d cant find %llu in active[%d]\n",sp->myslot,sp->myind,(long long)nxt64bits,sp->numactive); |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits) |
|||
{ |
|||
int32_t i; struct pangea_info *sp; |
|||
if ( dp != 0 && (sp= dp->table) != 0 ) |
|||
{ |
|||
for (i=0; i<sp->numaddrs; i++) |
|||
if ( sp->addrs[i] == destbits ) |
|||
return(i); |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t pangea_addplayer(struct cards777_pubdata *dp,struct pangea_info *sp,bits256 clientpub) |
|||
{ |
|||
int32_t i,n,openslot = -1; uint64_t nxt64bits = acct777_nxt64bits(clientpub); |
|||
for (i=n=0; i<sp->numaddrs; i++) |
|||
{ |
|||
if ( sp->addrs[i] == nxt64bits ) |
|||
{ |
|||
PNACL_message("pangea_addplayer: player %llu already in addrs[%d]\n",(long long)nxt64bits,i); |
|||
return(-1); |
|||
} |
|||
if ( sp->balances[i] <= 0 ) |
|||
openslot = i; |
|||
} |
|||
if ( openslot < 0 || sp->numactive >= sp->numaddrs-1 ) |
|||
{ |
|||
PNACL_message("pangea_addplayer: no room to add %llu\n",(long long)nxt64bits); |
|||
return(-1); |
|||
} |
|||
dp->readymask &= ~(1 << openslot); |
|||
sp->addrs[openslot] = nxt64bits; |
|||
sp->playerpubs[openslot] = clientpub; |
|||
sp->active[sp->numactive++] = nxt64bits; |
|||
if ( sp->myslot == 0 ) |
|||
{ |
|||
uint64_t isbot[CARDS777_MAXPLAYERS]; char *retbuf = malloc(65536); |
|||
if ( retbuf != 0 ) |
|||
{ |
|||
pangeanet777_replace(sp->tp->hn.server,clientpub,openslot); |
|||
for (i=0; i<sp->numactive; i++) |
|||
isbot[i] = sp->isbot[i]; |
|||
pangea_create_newtable(retbuf,sp,dp,isbot); |
|||
pangeanet777_msg(nxt64bits,clientpub,&sp->tp->hn,0,retbuf,(int32_t)strlen(retbuf)+1); |
|||
free(retbuf); |
|||
} |
|||
} |
|||
pangea_neworder(dp,sp,0,0); |
|||
return(n); |
|||
} |
|||
|
|||
bits256 pangea_destpub(uint64_t destbits) |
|||
{ |
|||
int32_t i,haspubkey; bits256 destpub; char destNXT[64]; |
|||
memset(destpub.bytes,0,sizeof(destpub)); |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
if ( TABLES[i] != 0 && TABLES[i]->tp->nxt64bits == destbits ) |
|||
{ |
|||
destpub = TABLES[i]->tp->hn.client->H.pubkey; |
|||
break; |
|||
} |
|||
if ( i == sizeof(TABLES)/sizeof(*TABLES) ) |
|||
{ |
|||
expand_nxt64bits(destNXT,destbits); |
|||
destpub = issue_getpubkey(&haspubkey,destNXT); |
|||
} |
|||
return(destpub); |
|||
} |
|||
|
|||
struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
if ( TABLES[i] != 0 && tableid == TABLES[i]->tableid && (threadid < 0 || TABLES[i]->tp->threadid == threadid) ) |
|||
return(TABLES[i]); |
|||
return(0); |
|||
} |
|||
|
|||
struct pangea_info *pangea_find64(uint64_t tableid,uint64_t nxt64bits) |
|||
{ |
|||
int32_t i,j; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
{ |
|||
if ( TABLES[i] != 0 && (tableid == 0 || tableid == TABLES[i]->tableid) && TABLES[i]->tp != 0 ) |
|||
{ |
|||
for (j=0; j<TABLES[i]->numaddrs; j++) |
|||
{ |
|||
if ( TABLES[i]->addrs[j] == nxt64bits ) |
|||
return(TABLES[i]); |
|||
} |
|||
} |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
void pangea_free(struct pangea_info *sp) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++) |
|||
if ( TABLES[i] == sp ) |
|||
{ |
|||
TABLES[i] = 0; |
|||
break; |
|||
} |
|||
PNACL_message("PANGEA PURGE %llu\n",(long long)sp->tableid); |
|||
free(sp); |
|||
} |
|||
|
@ -0,0 +1,644 @@ |
|||
// from http://www.azillionmonkeys.com/qed/poker.zip
|
|||
// shamelessly copied from azillionmonkeys. getting millions of evals per second!
|
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <stdint.h> |
|||
#include <time.h> |
|||
#include <unistd.h> |
|||
|
|||
#define CLUB_SUIT (1) |
|||
#define DIAMOND_SUIT (2) |
|||
#define HEART_SUIT (4) |
|||
#define SPADE_SUIT (8) |
|||
|
|||
#define RANK_SHL (27) |
|||
#define SUBR_SHL (13) |
|||
#define SUBR_SHLMASK ((1<<SUBR_SHL)-1) |
|||
|
|||
#define STRAIGHT_FLUSH_SCORE (8 << RANK_SHL) |
|||
#define FOUR_KIND_SCORE (7 << RANK_SHL) |
|||
#define FULL_HOUSE_SCORE (6 << RANK_SHL) |
|||
#define FLUSH_SCORE (5 << RANK_SHL) |
|||
#define STRAIGHT_SCORE (4 << RANK_SHL) |
|||
#define THREE_KIND_SCORE (3 << RANK_SHL) |
|||
#define TWO_PAIR_SCORE (2 << RANK_SHL) |
|||
#define TWO_KIND_SCORE (1 << RANK_SHL) |
|||
|
|||
#define ONE_PAIR_SCORE (TWO_KIND_SCORE) |
|||
|
|||
typedef uint8_t u8; |
|||
typedef int8_t s8; |
|||
typedef uint32_t u32; |
|||
typedef int32_t s32; |
|||
|
|||
typedef struct { int32_t len; u8 entry[52]; } CardPileType; |
|||
|
|||
static char *handstrs[16] = { "high card", "one pair", "two pair", "three of a kind", "straight", "flush", "full house", "four of a kind", "straight flush", "err", "err", "err", "err", "err", "err", "err" }; |
|||
static char *kickerstrs[16] = { "", "kickers", "kicker", "kickers", "high", "high", "full of", "kicker", "high", "err", "err", "err", "err", "err", "err", "err" }; |
|||
|
|||
static u32 CardValue[52] = { |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 |
|||
}; |
|||
|
|||
static u32 CardSuit[52] = { |
|||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
|||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 |
|||
}; |
|||
|
|||
int32_t cardstr(char *cardstr,uint8_t card) |
|||
{ |
|||
int32_t suit; char *cardc = "A234567890JQK",suitc[4] = { 'C', 'D', 'H', 'S' }; |
|||
suit = card / 13; |
|||
card %= 13; |
|||
if ( card == 9 ) |
|||
sprintf(cardstr,"10%c",suitc[suit]); |
|||
else sprintf(cardstr,"%c%c",cardc[card],suitc[suit]); |
|||
return(card); |
|||
} |
|||
|
|||
static u32 CardSuitIdx[52] = { |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
|||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 |
|||
}; |
|||
|
|||
static u32 CardMask[52] = { |
|||
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, |
|||
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, |
|||
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, |
|||
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000 |
|||
}; |
|||
|
|||
static u32 FiveCardDrawScoreFast (u32 c0, u32 c1, u32 c2, u32 c3, u32 c4, u32 u) |
|||
{ |
|||
u32 y,z,m1,m2,m3,m4; |
|||
// Test for single suitedness
|
|||
u = u & (u - 1); |
|||
// Build masks of 1, 2, 3, and 4 of a kind.
|
|||
m1 = c0 | c1; |
|||
m2 = c1 & c0; |
|||
|
|||
m2 |= c2 & m1; |
|||
m1 |= c2; |
|||
|
|||
m2 |= c3 & m1; |
|||
m1 |= c3; |
|||
|
|||
m2 |= c4 & m1; |
|||
m1 |= c4; |
|||
|
|||
if (m2 == 0) { // No pairs?
|
|||
// Is the mask a sequence of 1 bits?
|
|||
z = m1 & (m1 - 1); |
|||
z ^= m1; |
|||
y = (z << 5) - z; |
|||
// Deal with the bicycle/wheel 5,4,3,2,Ace straight
|
|||
if (m1 == 0x100F) { |
|||
if (u != 0) return STRAIGHT_SCORE + 0xF; |
|||
return STRAIGHT_FLUSH_SCORE + 0xF; |
|||
} |
|||
if (y == m1) { |
|||
if (u != 0) return STRAIGHT_SCORE + m1; |
|||
return STRAIGHT_FLUSH_SCORE + m1; |
|||
} |
|||
if (u != 0) return m1; // Nothing
|
|||
return FLUSH_SCORE + m1; |
|||
} |
|||
/*
|
|||
// m1 = c0 | ... | c4
|
|||
// m2 = (c0 & c1) | ((c0|c1) & c2) | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4)
|
|||
// m3 = mask of 3 or 4 of a kind.
|
|||
// m4 = mask of 4 of a kind.
|
|||
*/ |
|||
m1 = c0 | c1; |
|||
m2 = c1 & c0; |
|||
|
|||
m3 = c2 & m2; |
|||
m2 |= c2 & m1; |
|||
m1 |= c2; |
|||
|
|||
m4 = c3 & m3; |
|||
m3 |= c3 & m2; |
|||
m2 |= c3 & m1; |
|||
m1 |= c3; |
|||
|
|||
m4 |= c4 & m3; |
|||
m3 |= c4 & m2; |
|||
m2 |= c4 & m1; |
|||
m1 |= c4; |
|||
|
|||
m1 &= ~m2; |
|||
if (m3 == 0) { |
|||
if ((m2 & (m2 - 1)) == 0) |
|||
return TWO_KIND_SCORE + (m2 << SUBR_SHL) + m1; |
|||
return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + m1; |
|||
} |
|||
m2 &= ~m3; |
|||
if (m4 == 0) { |
|||
if (m2 == 0) |
|||
return THREE_KIND_SCORE + (m3 << SUBR_SHL) + m1; |
|||
return FULL_HOUSE_SCORE + (m3 << SUBR_SHL) + m2; |
|||
} |
|||
return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1; |
|||
} |
|||
|
|||
static u32 FiveCardDrawScore (const u8 * h) |
|||
{ |
|||
u32 c0, c1, c2, c3, c4,u; |
|||
// Make suits powers of two.
|
|||
u = CardSuit[h[0]]; |
|||
u |= CardSuit[h[1]]; |
|||
u |= CardSuit[h[2]]; |
|||
u |= CardSuit[h[3]]; |
|||
u |= CardSuit[h[4]]; |
|||
// Make cards powers of two.
|
|||
c0 = CardMask[h[0]]; |
|||
c1 = CardMask[h[1]]; |
|||
c2 = CardMask[h[2]]; |
|||
c3 = CardMask[h[3]]; |
|||
c4 = CardMask[h[4]]; |
|||
return FiveCardDrawScoreFast (c0, c1, c2, c3, c4, u); |
|||
} |
|||
|
|||
static u32 SevenCardDrawFlush (const u8 * h, const u32 c[7]) |
|||
{ |
|||
static s32 LG2TAB[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3}; |
|||
u32 i,t,f[4]; s32 cc[4],s; |
|||
// Make suits powers of two.
|
|||
// There is at most one flush in a 7 card hand. So up to 4 masks arecreated, each being the set of cards in one particular suit.
|
|||
// As themasks are created a maximum countdown from 4 is tracked.
|
|||
#if 0 |
|||
s = (((((u32 *) h)[1])) * 5) & 0x00C0C0C0; |
|||
i = (((((u32 *) h)[0])) * 5) & 0xC0C0C0C0; |
|||
s = ((s * (1 + 64 + 4096)) >> 8) & 0x3F00; |
|||
i = ((i * (1 + 64 + 4096 + 262144)) >> 24) | s; |
|||
#endif |
|||
|
|||
f[0] = f[1] = f[2] = f[3] = 0; |
|||
cc[0] = cc[1] = cc[2] = cc[3] = 4; |
|||
|
|||
i = CardSuitIdx[h[0]]; |
|||
f[i] = c[0]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[1]]; |
|||
f[i] |= c[1]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[2]]; |
|||
f[i] |= c[2]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[3]]; |
|||
f[i] |= c[3]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[4]]; |
|||
f[i] |= c[4]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[5]]; |
|||
f[i] |= c[5]; cc[i]--; |
|||
|
|||
i = CardSuitIdx[h[6]]; |
|||
f[i] |= c[6]; cc[i]--; |
|||
|
|||
// If any of the counts goes below 0, then that suit has at least 5 cards in it.
|
|||
|
|||
if (((cc[0] | cc[1]) | (cc[2] | cc[3])) < 0) { |
|||
|
|||
// Map the negative count (of which there is at most 1) to the suit index.
|
|||
|
|||
s = (((cc[0] & 8) | (cc[1] & 16)) | ((cc[2] & 32) | (cc[3] & 64))) >> 3; |
|||
s = LG2TAB[s]; |
|||
|
|||
// Work out the top 5 cards, so that the proper flush is also known ...
|
|||
|
|||
t = f[s]; |
|||
while (cc[s] < -1) { |
|||
t &= t - 1; // Rip off last bit.
|
|||
cc[s]++; |
|||
} |
|||
|
|||
// ... but also keep the low part so that all straight flushes can still be tested for.
|
|||
|
|||
return f[s] | (t << SUBR_SHL); |
|||
} |
|||
// 0 -> indicates there is no flush in the hand.
|
|||
return 0; |
|||
} |
|||
|
|||
#define SevenCardDrawFlushScore(f) (FLUSH_SCORE + ((f) >> SUBR_SHL)) |
|||
|
|||
u32 SevenCardDrawScore (const u8 * h) |
|||
{ |
|||
u32 c[7],f, t, s, u, v,m1, m2, m3, m4; |
|||
c[0] = CardMask[h[0]]; |
|||
c[1] = CardMask[h[1]]; |
|||
c[2] = CardMask[h[2]]; |
|||
c[3] = CardMask[h[3]]; |
|||
c[4] = CardMask[h[4]]; |
|||
c[5] = CardMask[h[5]]; |
|||
c[6] = CardMask[h[6]]; |
|||
// Work out flush mask always, since its only redundant in the case of a full house or 4 of a kind.
|
|||
f = SevenCardDrawFlush (h, c); |
|||
// t is the full card mask
|
|||
t = ((c[0] | c[1]) | (c[2] | c[3])) | (c[4] | c[5] | c[6]); |
|||
// If 7 cards are found in a row ...
|
|||
s = t & (t - 1); |
|||
v = s ^ t; |
|||
u = (v << 7) - 1; |
|||
u &= ~(u >> 7); |
|||
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|||
if ((u & t) == u) { |
|||
if (f) { |
|||
// Intersect the flush mask with the straight mask to try to figure out if we have a straight flush.
|
|||
s = f & u; |
|||
u = s & (s - 1); |
|||
u ^= s; |
|||
u = (u << 7) - 1; |
|||
u &= ~(u >> 5); |
|||
t = u >> 1; |
|||
v = u >> 2; |
|||
if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u; |
|||
if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t; |
|||
if ((v & s) == v) return STRAIGHT_FLUSH_SCORE + v; |
|||
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|||
if ((0x100F & f) == 0x100F) |
|||
return STRAIGHT_FLUSH_SCORE + 0xF; |
|||
return SevenCardDrawFlushScore (f); |
|||
} |
|||
u &= ~(u >> 5); |
|||
return STRAIGHT_SCORE + u; |
|||
} |
|||
// If at most 6 cards are found in a row ...
|
|||
u = (v << 6) - 1; |
|||
u &= ~(u >> 6); |
|||
if ((u & t) != u) { |
|||
u = s & (s - 1); |
|||
u ^= s; |
|||
u = (u << 6) - 1; |
|||
u &= ~(u >> 6); |
|||
} |
|||
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|||
if ((u & t) == u) { |
|||
if (f) { |
|||
s = f & u; |
|||
u = s & (s - 1); |
|||
u ^= s; |
|||
u = (u << 6) - 1; |
|||
u &= ~(u >> 5); |
|||
t = u >> 1; |
|||
if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u; |
|||
if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t; |
|||
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|||
if ((0x100F & f) == 0x100F) |
|||
return STRAIGHT_FLUSH_SCORE + 0xF; |
|||
return SevenCardDrawFlushScore (f); |
|||
} |
|||
u &= ~(u >> 5); |
|||
return STRAIGHT_SCORE + u; |
|||
} |
|||
// If at most 5 cards are found in a row ...
|
|||
u = (v << 5) - 1; |
|||
u &= ~(u >> 5); |
|||
if ((u & t) != u) { |
|||
v = s; |
|||
s = s & (s - 1); |
|||
v ^= s; |
|||
u = (v << 5) - 1; |
|||
u &= ~(u >> 5); |
|||
if ((u & t) != u) { |
|||
u = s & (s - 1); |
|||
s ^= u; |
|||
u = (s << 5) - 1; |
|||
u &= ~(u >> 5); |
|||
} |
|||
} |
|||
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|||
if ((u & t) == u) { |
|||
if (f) { |
|||
s = f & u; |
|||
u = s & (s - 1); |
|||
u ^= s; |
|||
u = (u << 5) - 1; |
|||
u &= ~(u >> 5); |
|||
if ((u & s) == u) { |
|||
return STRAIGHT_FLUSH_SCORE + u; |
|||
} |
|||
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|||
if ((0x100F & f) == 0x100F) |
|||
return STRAIGHT_FLUSH_SCORE + 0xF; |
|||
return SevenCardDrawFlushScore (f); |
|||
} |
|||
u &= ~(u >> 5); |
|||
return STRAIGHT_SCORE + u; |
|||
} |
|||
// Deal with the bicycle/wheel 5,4,3,2,Ace straight
|
|||
if ((0x100F & t) == 0x100F) { |
|||
if (f) |
|||
{ |
|||
if ((0x100F & f) == 0x100F) |
|||
return STRAIGHT_FLUSH_SCORE + 0xF; |
|||
return SevenCardDrawFlushScore (f); |
|||
} |
|||
return STRAIGHT_SCORE + 0xF; |
|||
} |
|||
/*
|
|||
// m1 = c0 | ... | c4
|
|||
// m2 = (c0 & c1) | ((c0|c1) & c2) | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4)
|
|||
// m3 = mask of 3 or 4 of a kind.
|
|||
// m4 = mask of 4 of a kind.
|
|||
*/ |
|||
|
|||
m1 = c[0] | c[1]; |
|||
m2 = c[1] & c[0]; |
|||
|
|||
m3 = c[2] & m2; |
|||
m2 |= c[2] & m1; |
|||
m1 |= c[2]; |
|||
|
|||
m4 = c[3] & m3; |
|||
m3 |= c[3] & m2; |
|||
m2 |= c[3] & m1; |
|||
m1 |= c[3]; |
|||
|
|||
m4 |= c[4] & m3; |
|||
m3 |= c[4] & m2; |
|||
m2 |= c[4] & m1; |
|||
m1 |= c[4]; |
|||
|
|||
m4 |= c[5] & m3; |
|||
m3 |= c[5] & m2; |
|||
m2 |= c[5] & m1; |
|||
m1 |= c[5]; |
|||
|
|||
m4 |= c[6] & m3; |
|||
m3 |= c[6] & m2; |
|||
m2 |= c[6] & m1; |
|||
m1 |= c[6]; |
|||
// Make sure the m1 is just the mask of singleton cards.
|
|||
m1 &= ~m2; |
|||
// No 3 or 4 of a kinds.
|
|||
if (m3 == 0) { |
|||
if (f) { |
|||
return SevenCardDrawFlushScore (f); |
|||
} |
|||
if (m2) { |
|||
s = m2 & (m2 - 1); |
|||
if (s == 0) { |
|||
t = m1 & (m1 - 1); |
|||
t &= (t - 1); |
|||
return TWO_KIND_SCORE + (m2 << SUBR_SHL) + t; |
|||
} |
|||
v = m1; |
|||
t = s & (s - 1); |
|||
if (t) { |
|||
v |= m2 ^ s; |
|||
m2 = s; |
|||
} else { |
|||
v &= (v - 1); |
|||
} |
|||
v &= (v - 1); |
|||
return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + v; |
|||
} |
|||
// Nothing -- just remove the two low cards.
|
|||
m1 &= (m1 - 1); |
|||
m1 &= (m1 - 1); |
|||
return m1; |
|||
} |
|||
// 4 of a kind.
|
|||
if (m4) { |
|||
m1 |= (m2 & ~m4); |
|||
while ((m2 = (m1 & (m1 - 1))) != 0) { |
|||
m1 = m2; |
|||
} |
|||
return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1; |
|||
} |
|||
// 3 of a kind, but no other pair in the hand
|
|||
if ((m2 & ~m3) == 0) { |
|||
t = m3 & (m3 - 1); |
|||
// Two 3 of a kinds => Full House
|
|||
if (t) |
|||
return FULL_HOUSE_SCORE + (t << SUBR_SHL) + (m3 ^ t); |
|||
if (f) |
|||
return SevenCardDrawFlushScore (f); |
|||
// Just remove the two low cards, and score this as 3 of a kind.
|
|||
m1 &= (m1 - 1); |
|||
m1 &= (m1 - 1); |
|||
return THREE_KIND_SCORE + (m3 << SUBR_SHL) + m1; |
|||
} |
|||
// 3 of a kind and a seperate 2 of a kind (full house.)
|
|||
m2 &= ~m3; |
|||
t = m2 & (m2 - 1); |
|||
// If there are two 2 pairs in the hand, then pick the higher pair
|
|||
if (!t) t = m2; |
|||
return FULL_HOUSE_SCORE + (m3 << SUBR_SHL) + t; |
|||
} |
|||
|
|||
// Just a brute force 7 card draw ranking by picking each of the possible two cards to be skipped, and finding the score which is highest amongst the 21 possible 5 card sub-hands.
|
|||
u32 SevenCardDrawScoreSlow (const u8 * h) { |
|||
s32 i, j, k; |
|||
u32 r, m; |
|||
u8 h2[5]; |
|||
|
|||
m = 0; |
|||
for (i=0; i < 6; i++) { |
|||
for (k=0; k < i; k++) { |
|||
h2[k] = h[k]; |
|||
} |
|||
for (j=i+1; j < 7; j++) { |
|||
for (k=i+1; k < j; k++) { |
|||
h2[k-1] = h[k]; |
|||
} |
|||
for (k=j+1; k < 7; k++) { |
|||
h2[k-2] = h[k]; |
|||
} |
|||
r = FiveCardDrawScore (h2); |
|||
if (r > m) m = r; |
|||
} |
|||
} |
|||
return m; |
|||
} |
|||
|
|||
// A correctly distributed (ignoring the problem of using "rand() % x") reshuffling of your cards.
|
|||
static void Shuffle (CardPileType * c) |
|||
{ |
|||
int32_t i, j, k; u8 t; |
|||
for (i = 0; i < (c->len - 1); i++) |
|||
{ |
|||
k = (RAND_MAX / (c->len - i)) * (c->len - i); |
|||
do { |
|||
j = rand (); |
|||
} while (j >= k); |
|||
j = i + (j % (c->len - i)); |
|||
t = c->entry[i]; |
|||
c->entry[i] = c->entry[j]; |
|||
c->entry[j] = t; |
|||
} |
|||
} |
|||
|
|||
static int32_t Deal (CardPileType * h, CardPileType * d, int32_t n) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i < n && d->len > 0; i++) |
|||
{ |
|||
d->len--; |
|||
h->entry[ h->len ] = d->entry[ d->len ]; |
|||
h->len++; |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
static void InitDeck (CardPileType * deck) |
|||
{ |
|||
u8 i; |
|||
deck->len = 52; |
|||
for (i=0; i < 52; i++) deck->entry[i] = i; |
|||
} |
|||
|
|||
static void DisplayCard (u8 c, char out[]) |
|||
{ |
|||
// char suitdisp[9] = { 0, 5, 4, 0, 3, 0, 0, 0, 6 };
|
|||
static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' }; |
|||
char s[4]; |
|||
s[0] = " 1 "[CardValue[c]]; |
|||
s[1] = "234567890JQKA"[CardValue[c]]; |
|||
s[2] = suitdisp[CardSuit[c]]; |
|||
s[3] = '\0'; |
|||
strcat (out, " "); |
|||
strcat (out, s); |
|||
} |
|||
|
|||
void DisplayHand5 (const CardPileType * h) { |
|||
char out[128]; |
|||
int i; |
|||
|
|||
out[0] = '\0'; |
|||
for (i=0; i < 5; i++) DisplayCard (h->entry[i], out); |
|||
sprintf (out + strlen (out), " => %08X\n", (int)FiveCardDrawScore (&h->entry[0])); |
|||
printf ("%s", out); |
|||
} |
|||
|
|||
void set_cardstr(char *cardstr,uint32_t c) |
|||
{ |
|||
/*static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' };
|
|||
cardstr[0] = " 1 "[CardValue[c % 13]]; |
|||
cardstr[1] = "234567890JQKA"[CardValue[c % 13]]; |
|||
cardstr[2] = suitdisp[CardSuit[c]]; |
|||
cardstr[3] = '\0';*/ |
|||
|
|||
int32_t i,j=0; |
|||
c >>= 1; |
|||
for (i=12; i>=0; i--) |
|||
if ( ((1 << i) & c) != 0 ) |
|||
{ |
|||
cardstr[j++] = " 1 "[i]; |
|||
cardstr[j++] = "234567890JQKA"[i]; |
|||
cardstr[j++] = ' '; |
|||
} |
|||
cardstr[j++] = 0; |
|||
} |
|||
|
|||
uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose) |
|||
{ |
|||
char cardstr[32],cardstr2[32],*kickerstr,*str; uint32_t score,i; |
|||
handstr[0] = 0; |
|||
if ( cards == 0 ) |
|||
{ |
|||
handstr[0] = 0; |
|||
printf("set_handstr: null cards??\n"); |
|||
return(0); |
|||
} |
|||
for (i=0; i<7; i++) |
|||
if ( cards[i] < 0 || cards[i] >= 52 ) |
|||
{ |
|||
//printf("illegal card[%d] %d\n",i,cards[i]);
|
|||
return(0); |
|||
} |
|||
score = SevenCardDrawScore (&cards[0]); |
|||
set_cardstr(cardstr,(score>>SUBR_SHL) & SUBR_SHLMASK); |
|||
set_cardstr(cardstr2,score & SUBR_SHLMASK); |
|||
kickerstr = kickerstrs[(score>>RANK_SHL)&15]; |
|||
str = handstrs[(score>>RANK_SHL)&15]; |
|||
if ( verbose != 0 ) |
|||
{ |
|||
if ( strcmp(kickerstr,"high") == 0 ) |
|||
sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str); |
|||
else if ( strcmp(str,"full house") == 0 ) |
|||
sprintf(handstr,"%c%c full of %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); |
|||
else if ( strcmp(str,"three of a kind") == 0 ) |
|||
sprintf(handstr,"set of %c%c with kickers %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1],cardstr2[3],cardstr2[4]); |
|||
else if ( strcmp(str,"two pair") == 0 ) |
|||
sprintf(handstr,"two pair %c%c and %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr[3],cardstr[4],cardstr2[0],cardstr2[1]); |
|||
else if ( strcmp(str,"one pair") == 0 ) |
|||
sprintf(handstr,"pair of %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); |
|||
else sprintf(handstr,"%s %s %s %s",str,cardstr,kickerstr,cardstr2); |
|||
} |
|||
else |
|||
{ |
|||
if ( strcmp(kickerstr,"high") == 0 ) |
|||
sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str); |
|||
else if ( strcmp(str,"full house") == 0 ) |
|||
sprintf(handstr,"fullhouse %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); |
|||
else if ( strcmp(str,"three of a kind") == 0 ) |
|||
sprintf(handstr,"trip %c%c",cardstr[0],cardstr[1]); |
|||
else if ( strcmp(str,"two pair") == 0 ) |
|||
sprintf(handstr,"two pairs %c%c %c%c",cardstr[0],cardstr[1],cardstr[3],cardstr[4]); |
|||
else if ( strcmp(str,"one pair") == 0 ) |
|||
sprintf(handstr,"pair %c%c",cardstr[0],cardstr[1]); |
|||
else sprintf(handstr,"%s",cardstr2); |
|||
} |
|||
return(score); |
|||
} |
|||
|
|||
void DisplayHand7(char *handstr,uint8_t *cards) |
|||
{ |
|||
uint32_t x,y; int32_t i; char out[512]; |
|||
out[0] = '\0'; |
|||
for (i=0; i<7; i++) |
|||
DisplayCard (cards[i], out); |
|||
x = SevenCardDrawScore (cards); |
|||
y = SevenCardDrawScoreSlow (cards); |
|||
set_handstr(handstr,cards,1); |
|||
if ( x != y ) |
|||
fprintf(stderr,"Error slow score %08x vs fast score %08x???\n",y,x); |
|||
sprintf (out + strlen (out), " => %08x %6d %6d -> (%s)",x,(x>>SUBR_SHL)&SUBR_SHLMASK,x&SUBR_SHLMASK,handstr); |
|||
printf("%s\n",out); |
|||
} |
|||
|
|||
void poker_test() |
|||
{ |
|||
char *_mbstr(double n); |
|||
CardPileType Deck,Hands[1000]; uint32_t c,starttime,score; uint64_t total,counter; char handstr[512]; uint8_t *cards; |
|||
//srand (0);
|
|||
InitDeck (&Deck); |
|||
Shuffle (&Deck); |
|||
for (c=0; c<(sizeof(Hands)/sizeof(*Hands)); c++) |
|||
{ |
|||
Deal (&Hands[c],&Deck,7); |
|||
DisplayHand7(handstr,Hands[c].entry); |
|||
Deal (&Deck,&Hands[c],7); |
|||
Shuffle(&Deck); |
|||
} |
|||
starttime = (uint32_t)time(NULL); |
|||
#ifndef _WIN32 |
|||
while ( (uint32_t)time(NULL) == starttime ) |
|||
usleep(100); |
|||
total = counter = 0; |
|||
while ( (uint32_t)time(NULL) < starttime+11 ) |
|||
{ |
|||
for (c=0; c<1000; c++,counter++) |
|||
{ |
|||
cards = Hands[c % (sizeof(Hands)/sizeof(*Hands))].entry; |
|||
score = SevenCardDrawScore(cards); |
|||
total += score; |
|||
} |
|||
} |
|||
char *mbstr(char *str,double val); |
|||
char str[65]; printf("counter.%llu %s in 10 seconds: ave score %llx\n",(long long)counter,mbstr(str,counter),(long long)(total/counter)); |
|||
#endif |
|||
} |
Loading…
Reference in new issue