Merge pull request #1370 from jl777/jl777

Jl777
This commit is contained in:
jl777
2019-04-01 05:37:22 -11:00
committed by GitHub
48 changed files with 7424 additions and 4611 deletions

View File

@@ -197,6 +197,7 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector<uint8_t> payload);
int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t len);
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets);
@@ -247,6 +248,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, c
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
bool IsCCInput(CScript const& scriptSig);
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime);
int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str);
uint256 revuint256(uint256 txid);

View File

@@ -168,6 +168,18 @@ bool IsCCInput(CScript const& scriptSig)
return true;
}
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
{
int64_t interest; uint64_t valuein;
CCoinsViewCache &view = *pcoinsTip;
valuein = view.GetValueIn(height,&interest,tx,blocktime);
if ( valuein-tx.GetValueOut() > txfee )
{
//fprintf(stderr, "txfee.%li vs txfee.%li\n", valuein-tx.GetValueOut(), txfee);
return false;
}
return true;
}
// set additional 'unspendable' addr
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
@@ -668,4 +680,4 @@ bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,co
return(false); //eval->Invalid("error in CClib_validate");
}
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
}
}

View File

@@ -52,6 +52,8 @@ std::string MYCCLIBNAME = (char *)"sudoku";
void komodo_netevent(std::vector<uint8_t> payload) {}
#endif
extern std::string MYCCLIBNAME;
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
struct CClib_rpcinfo
@@ -691,8 +693,8 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
#include "customcc.cpp"
#elif BUILD_GAMESCC
#include "gamescc.cpp"
#include "rogue/cursesd.c"
#include "gamescc.cpp"
#else
#include "sudoku.cpp"

1119
src/cc/dapps/dappstd.c Normal file

File diff suppressed because it is too large Load Diff

289
src/cc/games/prices.c Normal file
View File

@@ -0,0 +1,289 @@
#include "prices.h"
#include <time.h>
#include <unistd.h>
#ifdef BUILD_GAMESCC
#include "../rogue/cursesd.h"
#else
#include <curses.h>
#endif
#define SATOSHIDEN ((uint64_t)100000000L)
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"prices",cmdstr,0,0,0)
extern int64_t Net_change,Betsize;
int random_tetromino(struct games_state *rs)
{
rs->seed = _games_rngnext(rs->seed);
return(rs->seed % NUM_TETROMINOS);
}
int32_t pricesdata(struct games_player *P,void *ptr)
{
tetris_game *tg = (tetris_game *)ptr;
P->gold = tg->points;
P->dungeonlevel = tg->level;
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
return(0);
}
void sleep_milli(int milliseconds)
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = milliseconds * 1000 * 1000;
nanosleep(&ts, NULL);
}
struct games_state globalR;
extern char Gametxidstr[];
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
uint64_t get_btcusd();
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize);
void *gamesiterate(struct games_state *rs)
{
bool running = true; uint32_t eventid = 0; int64_t price;
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
initscr(); // initialize curses
cbreak(); // pass key presses to program, but not signals
noecho(); // don't echo key presses to screen
timeout(0);
}
while ( running != 0 )
{
//running = tg_tick(rs,tg,move);
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
}
if ( rs->guiflag != 0 )
{
#ifdef STANDALONE
price = get_btcusd();
//fprintf(stderr,"%llu -> t%u %.4f\n",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
//issue_games_events(rs,Gametxidstr,eventid,price);
issue_bet(rs,price,Betsize);
eventid++;
doupdate();
sleep(10);
switch ( getch() )
{
case '+': Net_change++; break;
case '-': Net_change--; break;
case '0': Net_change = 0; break;
case '$': Betsize = SATOSHIDEN; break;
case '^': Betsize += (Betsize >> 3); break;
case '/': Betsize -= (Betsize >> 3); break;
}
/*if ( (counter++ % 10) == 0 )
doupdate();
c = games_readevent(rs);
if ( c <= 0x7f || skipcount == 0x3fff )
{
if ( skipcount > 0 )
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
if ( c <= 0x7f )
issue_games_events(rs,Gametxidstr,eventid,c);
if ( tg->level != prevlevel )
{
flushkeystrokes(rs,0);
prevlevel = tg->level;
}
skipcount = 0;
} else skipcount++;*/
#endif
}
else
{
if ( rs->replaydone != 0 )
break;
if ( rs->sleeptime != 0 )
{
sleep_milli(1);
}
/*if ( skipcount == 0 )
{
c = games_readevent(rs);
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
if ( (c & 0x4000) == 0x4000 )
{
skipcount = (c & 0x3fff);
c = 'S';
}
}
if ( skipcount > 0 )
skipcount--;*/
}
eventid++;
}
return(0);
}
#ifdef STANDALONE
#include <ncurses.h>
#include "dapps/dappstd.c"
int64_t Net_change,Betsize = SATOSHIDEN;
char *send_curl(char *url,char *fname)
{
char *retstr;
retstr = issue_curl(url);
return(retstr);
}
cJSON *get_urljson(char *url,char *fname)
{
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= send_curl(url,fname)) != 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
//////////////////////////////////////////////
// start of dapp
//////////////////////////////////////////////
uint64_t get_btcusd()
{
cJSON *pjson,*bpi,*usd; char str[512]; uint64_t x,newprice,mult,btcusd = 0;
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json",(char *)"/tmp/oraclefeed.json")) != 0 )
{
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 && (usd= jobj(bpi,(char *)"USD")) != 0 )
{
btcusd = jdouble(usd,(char *)"rate_float") * SATOSHIDEN;
mult = 10000 + Net_change*10;
newprice = (btcusd * mult) / 10000;
x = ((uint64_t)time(NULL) << 32) | ((newprice / 10000) & 0xffffffff);
sprintf(str,"BTC/USD %.4f -> Betsize %.8f (^ / to change) && %.4f Net %.1f%% [+ - to change]\n",dstr(btcusd),dstr(Betsize),dstr(newprice),(double)100*(mult-10000)/10000);
mvaddstr(0, 0, str);
clrtoeol();
doupdate();
}
free_json(pjson);
}
return(x);
}
char *clonestr(char *str)
{
char *clone; int32_t len;
if ( str == 0 || str[0] == 0 )
{
printf("warning cloning nullstr.%p\n",str);
#ifdef __APPLE__
while ( 1 ) sleep(1);
#endif
str = (char *)"<nullstr>";
}
len = strlen(str);
clone = (char *)calloc(1,len+16);
strcpy(clone,str);
return(clone);
}
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
{
static FILE *fp;
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
if ( fp == 0 )
fp = fopen("events.log","wb");
rs->buffered[rs->num++] = c;
if ( 1 )
{
if ( sizeof(c) == 1 )
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
else if ( sizeof(c) == 2 )
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
else if ( sizeof(c) == 4 )
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
else if ( sizeof(c) == 8 )
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
if ( fp != 0 )
{
fprintf(fp,"%s\n",jprint(resobj,0));
fflush(fp);
}
}
free_json(retjson);
} else fprintf(fp,"error parsing %s\n",retstr);
free(retstr);
} else fprintf(fp,"error issuing method %s\n",params);
return(retval);
} else return(0);
}
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize)
{
char params[512],hexstr[64],*retstr; cJSON *retjson,*resobj; int32_t i,retval = -1;
memset(hexstr,0,sizeof(hexstr));
for (i=0; i<8; i++)
{
sprintf(&hexstr[i<<1],"%02x",(uint8_t)(x & 0xff));
x >>= 8;
}
sprintf(params,"[\"bet\",\"17\",\"[%.8f,%%22%s%%22]\"]",dstr(betsize),hexstr);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
//fprintf(stderr,"%s\n",jprint(resobj,0));
}
free_json(retjson);
}
free(retstr);
}
return(retval);
}
int prices(int argc, char **argv)
{
struct games_state *rs = &globalR;
int32_t c,skipcount=0; uint32_t eventid = 0;
memset(rs,0,sizeof(*rs));
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc >= 2 && strlen(argv[2]) == 64 )
{
#ifdef _WIN32
#ifdef _MSC_VER
rs->origseed = _strtoui64(argv[1], NULL, 10);
#else
rs->origseed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
rs->origseed = atol(argv[1]); // non-windows
#endif // _WIN32
rs->seed = rs->origseed;
if ( argc >= 3 )
{
strcpy(Gametxidstr,argv[2]);
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
{
fprintf(stderr,"invalid gametxid, or already started\n");
return(-1);
}
}
} else rs->seed = 777;
gamesiterate(rs);
//gamesbailout(rs);
return 0;
}
#endif

281
src/cc/games/prices.cpp Normal file
View File

@@ -0,0 +1,281 @@
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
std::string MYCCLIBNAME = (char *)"prices";
#define PRICES_BETPERIOD 3
UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag);
extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
#define bstr(x) ((double)((uint32_t)x) / 10000.)
struct prices_bar
{
uint64_t open,high,low,close,sum;
int32_t num;
};
int32_t prices_barupdate(struct prices_bar *bar,uint64_t pricebits)
{
uint32_t uprice,timestamp;
timestamp = (uint32_t)(pricebits >> 32);
uprice = (uint32_t)pricebits;
bar->sum += uprice, bar->num++;
if ( bar->open == 0 )
bar->open = bar->high = bar->low = pricebits;
if ( uprice > (uint32_t)bar->high )
bar->high = pricebits;
else if ( uprice < (uint32_t)bar->low )
bar->low = pricebits;
bar->close = pricebits;
return(0);
}
int64_t prices_bardist(struct prices_bar *bar,uint32_t aveprice,uint64_t pricebits)
{
int64_t a,dist = 0;
if ( aveprice != 0 )
{
a = (pricebits & 0xffffffff);
dist = (a - aveprice);
dist *= dist;
//fprintf(stderr,"dist.%lld (u %u - ave %u) %d\n",(long long)dist,uprice,aveprice,uprice-aveprice);
}
return(dist);
}
void prices_bardisp(struct prices_bar *bar)
{
if ( bar->num == 0 )
fprintf(stderr,"BAR null\n");
else fprintf(stderr,"BAR ave %.4f (O %.4f, H %.4f, L %.4f, C %.4f)\n",bstr(bar->sum/bar->num),bstr(bar->open),bstr(bar->high),bstr(bar->low),bstr(bar->close));
}
int64_t prices_blockinfo(int32_t height,char *acaddr)
{
std::vector<uint8_t> vopret; CBlockIndex *pindex; CBlock block; CTransaction tx,vintx; uint64_t pricebits; char destaddr[64]; uint32_t aveprice=0,timestamp,uprice; uint256 hashBlock; int64_t dist,mindist=(1LL<<60),prizefund = 0; int32_t mini=-1,i,n,vini,numvouts,iter; struct prices_bar refbar;
if ( (pindex= komodo_chainactive(height)) != 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
{
n = block.vtx.size();
vini = 0;
memset(&refbar,0,sizeof(refbar));
for (iter=0; iter<2; iter++)
{
for (i=0; i<n; i++)
{
tx = block.vtx[i];
if ( myGetTransaction(tx.vin[vini].prevout.hash,vintx,hashBlock) == 0 )
continue;
else if ( tx.vin[vini].prevout.n >= vintx.vout.size() || Getscriptaddress(destaddr,vintx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 )
continue;
else if ( (numvouts= tx.vout.size()) > 1 && tx.vout[numvouts-1].scriptPubKey[0] == 0x6a )
{
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
if ( vopret.size() == 8 )
{
E_UNMARSHAL(vopret,ss >> pricebits);
timestamp = (uint32_t)(pricebits >> 32);
uprice = (uint32_t)pricebits;
if ( iter == 0 )
{
prizefund += tx.vout[0].nValue;
if ( strcmp(acaddr,destaddr) == 0 )
{
//fprintf(stderr,"REF ");
prices_barupdate(&refbar,pricebits);
}
}
else if ( strcmp(acaddr,destaddr) != 0 )
{
dist = prices_bardist(&refbar,aveprice,pricebits);
if ( dist < mindist )
{
mindist = dist;
mini = i;
}
fprintf(stderr,"mini.%d i.%d %.8f t%u %.4f v.%d %s lag.%d i.%d dist.%lld\n",mini,i,(double)tx.vout[0].nValue/COIN,timestamp,(double)uprice/10000,numvouts,destaddr,(int32_t)(pindex->nTime-timestamp),iter,(long long)dist);
}
} else return(-3);
}
}
if ( iter == 0 )
{
prices_bardisp(&refbar);
if ( refbar.num != 0 )
aveprice = (uint32_t)refbar.sum / refbar.num;
}
}
return(prizefund);
} else return(-2);
} else return(-1);
}
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); char acaddr[64]; CPubKey acpk,mypk,gamespk; int64_t prizefund = 0; int32_t height,nextheight = komodo_nextheight();
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
return(result);
}
mypk = pubkey2pk(Mypubkey());
gamespk = GetUnspendable(cp,0);
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
Getscriptaddress(acaddr,CScript() << ParseHex(HexStr(acpk)) << OP_CHECKSIG);
if ( params != 0 && cJSON_GetArraySize(params) == 1 )
{
height = juint(jitem(params,0),0);
result.push_back(Pair("height",(int64_t)height));
if ( (prizefund= prices_blockinfo(height,acaddr)) < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("errorcode",prizefund));
result.push_back(Pair("error","blockinfo error"));
}
else
{
// display bets
if ( height <= nextheight-PRICES_BETPERIOD )
{
// settle bets by first nonzero reference bar
}
result.push_back(Pair("prizefund",ValueFromAmount(prizefund)));
result.push_back(Pair("result","success"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parse"));
}
return(result);
}
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; int64_t amount,inputsum; uint64_t price; CPubKey gamespk,mypk,acpk;
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
return(result);
}
mypk = pubkey2pk(Mypubkey());
gamespk = GetUnspendable(cp,0);
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
if ( params != 0 && cJSON_GetArraySize(params) == 2 )
{
amount = jdouble(jitem(params,0),0) * COIN + 0.0000000049;
if ( cclib_parsehash((uint8_t *)&price,jitem(params,1),8) < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parsehash"));
return(result);
}
if ( mypk == acpk )
{
amount = 0; // i am the reference price feed
//fprintf(stderr,"i am the reference\n");
}
//fprintf(stderr,"amount %llu price %llx\n",(long long)amount,(long long)price);
if ( (inputsum= AddNormalinputs(mtx,mypk,amount+GAMES_TXFEE,64)) >= amount+GAMES_TXFEE )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,gamespk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,GAMES_TXFEE,CScript() << OP_RETURN << price);
return(games_rawtxresult(result,rawtx,1));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","not enough funds"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parse"));
}
return(result);
}
void prices_update(uint32_t timestamp,uint32_t uprice,int32_t ismine)
{
//fprintf(stderr,"%s t%u %.4f %16llx\n",ismine!=0?"mine":"ext ",timestamp,(double)uprice/10000,(long long)((uint64_t)timestamp<<32) | uprice);
}
// game specific code for daemon
void games_packitemstr(char *packitemstr,struct games_packitem *item)
{
strcpy(packitemstr,"");
}
int64_t games_cashout(struct games_player *P)
{
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=1000,cashout = 0;
cashout = (uint64_t)P->gold * mult * dungeonlevel * dungeonlevel;
return(cashout);
}
void pricesplayerjson(UniValue &obj,struct games_player *P)
{
obj.push_back(Pair("packsize",(int64_t)P->packsize));
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
obj.push_back(Pair("level",(int64_t)P->level));
obj.push_back(Pair("experience",(int64_t)P->experience));
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
}
int32_t disp_gamesplayer(char *str,struct games_player *P)
{
str[0] = 0;
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
// return(-1);
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
return(0);
}
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
{
uint256 gametxid; int32_t i,len; char str[67]; int64_t price; uint32_t eventid = 0;
if ( (len= payload.size()) > 36 )
{
len -= 36;
for (i=0; i<32; i++)
((uint8_t *)&gametxid)[i] = payload[len+i];
eventid = (uint32_t)payload[len+32];
eventid |= (uint32_t)payload[len+33] << 8;
eventid |= (uint32_t)payload[len+34] << 16;
eventid |= (uint32_t)payload[len+35] << 24;
for (i=0; i<len&&i<sizeof(price); i++)
((uint8_t *)&price)[7-i] = payload[i];
prices_update((uint32_t)(price >> 32),(uint32_t)(price & 0xffffffff),pk == pubkey2pk(Mypubkey()));
//fprintf(stderr,"%llu -> t%u %.4f ",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
return(0);
} else return(-1);
}
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
return(true);
}

208
src/cc/games/prices.h Normal file
View File

@@ -0,0 +1,208 @@
#ifndef H_PRICES_H
#define H_PRICES_H
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
/*
Convert a tetromino type to its corresponding cell.
*/
#define TYPE_TO_CELL(x) ((x)+1)
/*
Strings for how you would print a tetris board.
*/
#define TC_EMPTY_STR " "
#define TC_BLOCK_STR "\u2588"
/*
Questions about a tetris cell.
*/
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
/*
How many cells in a tetromino?
*/
#define TETRIS 4
/*
How many tetrominos?
*/
#define NUM_TETROMINOS 7
/*
How many orientations of a tetromino?
*/
#define NUM_ORIENTATIONS 4
/*
Level constants.
*/
#define MAX_LEVEL 19
#define LINES_PER_LEVEL 10
/*
A "cell" is a 1x1 block within a tetris board.
*/
typedef enum {
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
} tetris_cell;
/*
A "type" is a type/shape of a tetromino. Not including orientation.
*/
typedef enum {
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
} tetris_type;
/*
A row,column pair. Negative numbers allowed, because we need them for
offsets.
*/
typedef struct {
int row;
int col;
} tetris_location;
/*
A "block" is a struct that contains information about a tetromino.
Specifically, what type it is, what orientation it has, and where it is.
*/
typedef struct {
int typ;
int ori;
tetris_location loc;
} tetris_block;
/*
All possible moves to give as input to the game.
*/
typedef enum {
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
} tetris_move;
/*
A game object!
*/
typedef struct {
/*
Game board stuff:
*/
int rows;
int cols;
/*
Scoring information:
*/
int points;
int level;
/*
Falling block is the one currently going down. Next block is the one that
will be falling after this one. Stored is the block that you can swap out.
*/
tetris_block falling;
tetris_block next;
tetris_block stored;
/*
Number of game ticks until the block will move down.
*/
int ticks_till_gravity;
/*
Number of lines until you advance to the next level.
*/
int lines_remaining;
char board[];
} tetris_game;
/*
This array stores all necessary information about the cells that are filled by
each tetromino. The first index is the type of the tetromino (i.e. shape,
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
array contains 4 tetris_location objects, each mapping to an offset from a
point on the upper left that is the tetromino "origin".
*/
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
/*
This array tells you how many ticks per gravity by level. Decreases as level
increases, to add difficulty.
*/
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
// Data structure manipulation.
void tg_init(tetris_game *obj, int rows, int cols);
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
void tg_destroy(tetris_game *obj);
void tg_delete(tetris_game *obj);
tetris_game *tg_load(FILE *f);
void tg_save(tetris_game *obj, FILE *f);
// Public methods not related to memory:
char tg_get(tetris_game *obj, int row, int col);
bool tg_check(tetris_game *obj, int row, int col);
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
void tg_print(tetris_game *obj, FILE *f);
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
#define GAMENAME "prices" // name of executable
#define GAMEMAIN prices // main program of game
#define GAMEPLAYERJSON pricesplayerjson // displays game specific json
#define GAMEDATA pricesdata // extracts data from game specific variables into games_state
#define CHAINNAME "PRICES" // -ac_name=
typedef uint64_t gamesevent; // can be 8, 16, 32, or 64 bits
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed,origseed;
char *keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
gamesevent buffered[5000],*keystrokes;
uint8_t playerdata[8192];
};
extern struct games_state globalR;
void *gamesiterate(struct games_state *rs);
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
uint64_t _games_rngnext(uint64_t initseed);
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
gamesevent games_revendian(gamesevent revx);
int32_t disp_gamesplayer(char *str,struct games_player *P);
#endif

904
src/cc/games/tetris.c Normal file
View File

@@ -0,0 +1,904 @@
#include "tetris.h"
/*
In order to port a game into gamesCC, the RNG needs to be seeded with the gametxid seed, also events needs to be broadcast using issue_games_events. Also the game engine needs to be daemonized, preferably by putting all globals into a single data structure.
also, the standalone game needs to support argv of seed gametxid, along with replay args
*/
int random_tetromino(struct games_state *rs)
{
rs->seed = _games_rngnext(rs->seed);
return(rs->seed % NUM_TETROMINOS);
}
int32_t tetrisdata(struct games_player *P,void *ptr)
{
tetris_game *tg = (tetris_game *)ptr;
P->gold = tg->points;
P->dungeonlevel = tg->level;
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
return(0);
}
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
#include <stdio.h> // for FILE
#include <stdbool.h> // for bool
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <string.h>
#ifdef BUILD_GAMESCC
#include "../rogue/cursesd.h"
#else
#include <curses.h>
#endif
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
/*******************************************************************************
Array Definitions
*******************************************************************************/
const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS] =
{
// I
{{{1, 0}, {1, 1}, {1, 2}, {1, 3}},
{{0, 2}, {1, 2}, {2, 2}, {3, 2}},
{{3, 0}, {3, 1}, {3, 2}, {3, 3}},
{{0, 1}, {1, 1}, {2, 1}, {3, 1}}},
// J
{{{0, 0}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {2, 1}},
{{1, 0}, {1, 1}, {1, 2}, {2, 2}},
{{0, 1}, {1, 1}, {2, 0}, {2, 1}}},
// L
{{{0, 2}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {1, 1}, {2, 1}, {2, 2}},
{{1, 0}, {1, 1}, {1, 2}, {2, 0}},
{{0, 0}, {0, 1}, {1, 1}, {2, 1}}},
// O
{{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}}},
// S
{{{0, 1}, {0, 2}, {1, 0}, {1, 1}},
{{0, 1}, {1, 1}, {1, 2}, {2, 2}},
{{1, 1}, {1, 2}, {2, 0}, {2, 1}},
{{0, 0}, {1, 0}, {1, 1}, {2, 1}}},
// T
{{{0, 1}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {1, 1}, {1, 2}, {2, 1}},
{{1, 0}, {1, 1}, {1, 2}, {2, 1}},
{{0, 1}, {1, 0}, {1, 1}, {2, 1}}},
// Z
{{{0, 0}, {0, 1}, {1, 1}, {1, 2}},
{{0, 2}, {1, 1}, {1, 2}, {2, 1}},
{{1, 0}, {1, 1}, {2, 1}, {2, 2}},
{{0, 1}, {1, 0}, {1, 1}, {2, 0}}},
};
const int GRAVITY_LEVEL[MAX_LEVEL+1] = {
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
50, 48, 46, 44, 42, 40, 38, 36, 34, 32,
//10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
30, 28, 26, 24, 22, 20, 16, 12, 8, 4
};
/*******************************************************************************
Helper Functions for Blocks
*******************************************************************************/
void sleep_milli(int milliseconds)
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = milliseconds * 1000 * 1000;
nanosleep(&ts, NULL);
}
/*
Return the block at the given row and column.
*/
char tg_get(tetris_game *obj, int row, int column)
{
return obj->board[obj->cols * row + column];
}
/*
Set the block at the given row and column.
*/
static void tg_set(tetris_game *obj, int row, int column, char value)
{
obj->board[obj->cols * row + column] = value;
}
/*
Check whether a row and column are in bounds.
*/
bool tg_check(tetris_game *obj, int row, int col)
{
return 0 <= row && row < obj->rows && 0 <= col && col < obj->cols;
}
/*
Place a block onto the board.
*/
static void tg_put(tetris_game *obj, tetris_block block)
{
int i;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col,
TYPE_TO_CELL(block.typ));
}
}
/*
Clear a block out of the board.
*/
static void tg_remove(tetris_game *obj, tetris_block block)
{
int i;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col, TC_EMPTY);
}
}
/*
Check if a block can be placed on the board.
*/
static bool tg_fits(tetris_game *obj, tetris_block block)
{
int i, r, c;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
r = block.loc.row + cell.row;
c = block.loc.col + cell.col;
if (!tg_check(obj, r, c) || TC_IS_FILLED(tg_get(obj, r, c))) {
return false;
}
}
return true;
}
/*
Create a new falling block and populate the next falling block with a random
one.
*/
static void tg_new_falling(struct games_state *rs,tetris_game *obj)
{
// Put in a new falling tetromino.
obj->falling = obj->next;
obj->next.typ = random_tetromino(rs);
obj->next.ori = 0;
obj->next.loc.row = 0;
obj->next.loc.col = obj->cols/2 - 2;
}
/*******************************************************************************
Game Turn Helpers
*******************************************************************************/
/*
Tick gravity, and move the block down if gravity should act.
*/
static void tg_do_gravity_tick(struct games_state *rs,tetris_game *obj)
{
obj->ticks_till_gravity--;
if (obj->ticks_till_gravity <= 0) {
tg_remove(obj, obj->falling);
obj->falling.loc.row++;
if (tg_fits(obj, obj->falling)) {
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
} else {
obj->falling.loc.row--;
tg_put(obj, obj->falling);
tg_new_falling(rs,obj);
}
tg_put(obj, obj->falling);
}
}
/*
Move the falling tetris block left (-1) or right (+1).
*/
static void tg_move(tetris_game *obj, int direction)
{
tg_remove(obj, obj->falling);
obj->falling.loc.col += direction;
if (!tg_fits(obj, obj->falling)) {
obj->falling.loc.col -= direction;
}
tg_put(obj, obj->falling);
}
/*
Send the falling tetris block to the bottom.
*/
static void tg_down(struct games_state *rs,tetris_game *obj)
{
tg_remove(obj, obj->falling);
while (tg_fits(obj, obj->falling)) {
obj->falling.loc.row++;
}
obj->falling.loc.row--;
tg_put(obj, obj->falling);
tg_new_falling(rs,obj);
}
/*
Rotate the falling block in either direction (+/-1).
*/
static void tg_rotate(tetris_game *obj, int direction)
{
tg_remove(obj, obj->falling);
while (true) {
obj->falling.ori = (obj->falling.ori + direction) % NUM_ORIENTATIONS;
// If the new orientation fits, we're done.
if (tg_fits(obj, obj->falling))
break;
// Otherwise, try moving left to make it fit.
obj->falling.loc.col--;
if (tg_fits(obj, obj->falling))
break;
// Finally, try moving right to make it fit.
obj->falling.loc.col += 2;
if (tg_fits(obj, obj->falling))
break;
// Put it back in its original location and try the next orientation.
obj->falling.loc.col--;
// Worst case, we come back to the original orientation and it fits, so this
// loop will terminate.
}
tg_put(obj, obj->falling);
}
/*
Swap the falling block with the block in the hold buffer.
*/
static void tg_hold(struct games_state *rs,tetris_game *obj)
{
tg_remove(obj, obj->falling);
if (obj->stored.typ == -1) {
obj->stored = obj->falling;
tg_new_falling(rs,obj);
} else {
int typ = obj->falling.typ, ori = obj->falling.ori;
obj->falling.typ = obj->stored.typ;
obj->falling.ori = obj->stored.ori;
obj->stored.typ = typ;
obj->stored.ori = ori;
while (!tg_fits(obj, obj->falling)) {
obj->falling.loc.row--;
if (tg_fits(obj, obj->falling)) {
break;
}
obj->falling.loc.col--;
if (tg_fits(obj, obj->falling)) {
break;
}
obj->falling.loc.col += 2;
}
}
tg_put(obj, obj->falling);
}
/*
Perform the action specified by the move.
*/
static void tg_handle_move(struct games_state *rs,tetris_game *obj, tetris_move move)
{
switch (move) {
case TM_LEFT:
//fprintf(stderr,"LEFT ");
tg_move(obj, -1);
break;
case TM_RIGHT:
//fprintf(stderr,"RIGHT ");
tg_move(obj, 1);
break;
case TM_DROP:
tg_down(rs,obj);
break;
case TM_CLOCK:
tg_rotate(obj, 1);
break;
case TM_COUNTER:
tg_rotate(obj, -1);
break;
case TM_HOLD:
tg_hold(rs,obj);
break;
default:
// pass
break;
}
}
/*
Return true if line i is full.
*/
static bool tg_line_full(tetris_game *obj, int i)
{
int j;
for (j = 0; j < obj->cols; j++) {
if (TC_IS_EMPTY(tg_get(obj, i, j)))
return false;
}
return true;
}
/*
Shift every row above r down one.
*/
static void tg_shift_lines(tetris_game *obj, int r)
{
int i, j;
for (i = r-1; i >= 0; i--) {
for (j = 0; j < obj->cols; j++) {
tg_set(obj, i+1, j, tg_get(obj, i, j));
tg_set(obj, i, j, TC_EMPTY);
}
}
}
/*
Find rows that are filled, remove them, shift, and return the number of
cleared rows.
*/
static int tg_check_lines(tetris_game *obj)
{
int i, nlines = 0;
tg_remove(obj, obj->falling); // don't want to mess up falling block
for (i = obj->rows-1; i >= 0; i--) {
if (tg_line_full(obj, i)) {
tg_shift_lines(obj, i);
i++; // do this line over again since they're shifted
nlines++;
}
}
tg_put(obj, obj->falling); // replace
return nlines;
}
/*
Adjust the score for the game, given how many lines were just cleared.
*/
static void tg_adjust_score(tetris_game *obj, int lines_cleared)
{
static int line_multiplier[] = {0, 40, 100, 300, 1200};
obj->points += line_multiplier[lines_cleared] * (obj->level + 1);
if (lines_cleared >= obj->lines_remaining) {
obj->level = MIN(MAX_LEVEL, obj->level + 1);
lines_cleared -= obj->lines_remaining;
obj->lines_remaining = LINES_PER_LEVEL - lines_cleared;
} else {
obj->lines_remaining -= lines_cleared;
}
}
/*
Return true if the game is over.
*/
static bool tg_game_over(tetris_game *obj)
{
int i, j;
bool over = false;
tg_remove(obj, obj->falling);
for (i = 0; i < 2; i++) {
for (j = 0; j < obj->cols; j++) {
if (TC_IS_FILLED(tg_get(obj, i, j))) {
over = true;
}
}
}
tg_put(obj, obj->falling);
return over;
}
/*******************************************************************************
Main Public Functions
*******************************************************************************/
/*
Do a single game tick: process gravity, user input, and score. Return true if
the game is still running, false if it is over.
*/
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move)
{
int lines_cleared;
// Handle gravity.
tg_do_gravity_tick(rs,obj);
// Handle input.
tg_handle_move(rs,obj, move);
// Check for cleared lines
lines_cleared = tg_check_lines(obj);
tg_adjust_score(obj, lines_cleared);
// Return whether the game will continue (NOT whether it's over)
return !tg_game_over(obj);
}
void tg_init(struct games_state *rs,tetris_game *obj, int rows, int cols)
{
// Initialization logic
obj->rows = rows;
obj->cols = cols;
//obj->board = (char *)malloc(rows * cols);
memset(obj->board, TC_EMPTY, rows * cols);
obj->points = 0;
obj->level = 0;
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
obj->lines_remaining = LINES_PER_LEVEL;
//srand(time(NULL));
tg_new_falling(rs,obj);
tg_new_falling(rs,obj);
obj->stored.typ = -1;
obj->stored.ori = 0;
obj->stored.loc.row = 0;
obj->next.loc.col = obj->cols/2 - 2;
//printf("%d", obj->falling.loc.col);
}
tetris_game *tg_create(struct games_state *rs,int rows, int cols)
{
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game) + rows*cols);
tg_init(rs,obj, rows, cols);
return obj;
}
/*void tg_destroy(tetris_game *obj)
{
// Cleanup logic
free(obj->board);
}*/
void tg_delete(tetris_game *obj) {
//tg_destroy(obj);
free(obj);
}
/*
Load a game from a file.
tetris_game *tg_load(FILE *f)
{
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game));
if (fread(obj, sizeof(tetris_game), 1, f) != 1 )
{
fprintf(stderr,"read game error\n");
free(obj);
obj = 0;
}
else
{
obj->board = (char *)malloc(obj->rows * obj->cols);
if (fread(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
{
fprintf(stderr,"fread error\n");
free(obj->board);
free(obj);
obj = 0;
}
}
return obj;
}*/
/*
Save a game to a file.
void tg_save(tetris_game *obj, FILE *f)
{
if (fwrite(obj, sizeof(tetris_game), 1, f) != 1 )
fprintf(stderr,"error writing tetrisgame\n");
else if (fwrite(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
fprintf(stderr,"error writing board\n");
}*/
/*
Print a game board to a file. Really just for early debugging.
*/
void tg_print(tetris_game *obj, FILE *f) {
int i, j;
for (i = 0; i < obj->rows; i++) {
for (j = 0; j < obj->cols; j++) {
if (TC_IS_EMPTY(tg_get(obj, i, j))) {
fputs(TC_EMPTY_STR, f);
} else {
fputs(TC_BLOCK_STR, f);
}
}
fputc('\n', f);
}
}
/*
2 columns per cell makes the game much nicer.
*/
#define COLS_PER_CELL 2
/*
Macro to print a cell of a specific type to a window.
*/
#define ADD_BLOCK(w,x) waddch((w),' '|A_REVERSE|COLOR_PAIR(x)); \
waddch((w),' '|A_REVERSE|COLOR_PAIR(x))
#define ADD_EMPTY(w) waddch((w), ' '); waddch((w), ' ')
/*
Print the tetris board onto the ncurses window.
*/
void display_board(WINDOW *w, tetris_game *obj)
{
int i, j;
box(w, 0, 0);
for (i = 0; i < obj->rows; i++) {
wmove(w, 1 + i, 1);
for (j = 0; j < obj->cols; j++) {
if (TC_IS_FILLED(tg_get(obj, i, j))) {
ADD_BLOCK(w,tg_get(obj, i, j));
} else {
ADD_EMPTY(w);
}
}
}
wnoutrefresh(w);
}
/*
Display a tetris piece in a dedicated window.
*/
void display_piece(WINDOW *w, tetris_block block)
{
int b;
tetris_location c;
wclear(w);
box(w, 0, 0);
if (block.typ == -1) {
wnoutrefresh(w);
return;
}
for (b = 0; b < TETRIS; b++) {
c = TETROMINOS[block.typ][block.ori][b];
wmove(w, c.row + 1, c.col * COLS_PER_CELL + 1);
ADD_BLOCK(w, TYPE_TO_CELL(block.typ));
}
wnoutrefresh(w);
}
/*
Display score information in a dedicated window.
*/
void display_score(WINDOW *w, tetris_game *tg)
{
wclear(w);
box(w, 0, 0);
wprintw(w, (char *)"Score\n%d\n", tg->points);
wprintw(w, (char *)"Level\n%d\n", tg->level);
wprintw(w, (char *)"Lines\n%d\n", tg->lines_remaining);
wnoutrefresh(w);
}
/*
Save and exit the game.
void save(tetris_game *game, WINDOW *w)
{
FILE *f;
wclear(w);
box(w, 0, 0); // return the border
wmove(w, 1, 1);
wprintw(w, (char *)"Save and exit? [Y/n] ");
wrefresh(w);
timeout(-1);
if (getch() == 'n') {
timeout(0);
return;
}
f = fopen("tetris.save", "w");
tg_save(game, f);
fclose(f);
tg_delete(game);
endwin();
fprintf(stderr,"Game saved to \"tetris.save\".\n");
fprintf(stderr,"Resume by passing the filename as an argument to this program.\n");
exit(EXIT_SUCCESS);
}*/
/*
Do the NCURSES initialization steps for color blocks.
*/
void init_colors(void)
{
start_color();
//init_color(COLOR_ORANGE, 1000, 647, 0);
init_pair(TC_CELLI, COLOR_CYAN, COLOR_BLACK);
init_pair(TC_CELLJ, COLOR_BLUE, COLOR_BLACK);
init_pair(TC_CELLL, COLOR_WHITE, COLOR_BLACK);
init_pair(TC_CELLO, COLOR_YELLOW, COLOR_BLACK);
init_pair(TC_CELLS, COLOR_GREEN, COLOR_BLACK);
init_pair(TC_CELLT, COLOR_MAGENTA, COLOR_BLACK);
init_pair(TC_CELLZ, COLOR_RED, COLOR_BLACK);
}
struct games_state globalR;
extern char Gametxidstr[];
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
gamesevent games_readevent(struct games_state *rs);
void *gamesiterate(struct games_state *rs)
{
uint32_t counter = 0; bool running = true; tetris_move move = TM_NONE;
gamesevent c; uint16_t skipcount=0; int32_t prevlevel; uint32_t eventid = 0; tetris_game *tg;
WINDOW *board, *next, *hold, *score;
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
// NCURSES initialization:
initscr(); // initialize curses
cbreak(); // pass key presses to program, but not signals
noecho(); // don't echo key presses to screen
keypad(stdscr, TRUE); // allow arrow keys
timeout(0); // no blocking on getch()
curs_set(0); // set the cursor to invisible
init_colors(); // setup tetris colors
}
tg = tg_create(rs,22, 10);
prevlevel = tg->level;
// Create windows for each section of the interface.
board = newwin(tg->rows + 2, 2 * tg->cols + 2, 0, 0);
next = newwin(6, 10, 0, 2 * (tg->cols + 1) + 1);
hold = newwin(6, 10, 7, 2 * (tg->cols + 1) + 1);
score = newwin(6, 10, 14, 2 * (tg->cols + 1 ) + 1);
while ( running != 0 )
{
running = tg_tick(rs,tg,move);
if ( 1 && (rs->guiflag != 0 || rs->sleeptime != 0) )
{
display_board(board,tg);
display_piece(next,tg->next);
display_piece(hold,tg->stored);
display_score(score,tg);
}
if ( rs->guiflag != 0 )
{
#ifdef STANDALONE
sleep_milli(15);
if ( (counter++ % 10) == 0 )
doupdate();
c = games_readevent(rs);
if ( c <= 0x7f || skipcount == 0x3fff )
{
if ( skipcount > 0 )
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
if ( c <= 0x7f )
issue_games_events(rs,Gametxidstr,eventid,c);
if ( tg->level != prevlevel )
{
flushkeystrokes(rs,0);
prevlevel = tg->level;
}
skipcount = 0;
} else skipcount++;
#endif
}
else
{
if ( rs->replaydone != 0 )
break;
if ( rs->sleeptime != 0 )
{
sleep_milli(1);
if ( (counter++ % 20) == 0 )
doupdate();
}
if ( skipcount == 0 )
{
c = games_readevent(rs);
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
if ( (c & 0x4000) == 0x4000 )
{
skipcount = (c & 0x3fff);
c = 'S';
}
}
if ( skipcount > 0 )
skipcount--;
}
eventid++;
switch ( c )
{
case 'h':
move = TM_LEFT;
break;
case 'l':
move = TM_RIGHT;
break;
case 'k':
move = TM_CLOCK;
break;
case 'j':
move = TM_DROP;
break;
case 'q':
running = false;
move = TM_NONE;
break;
/*case 'p':
wclear(board);
box(board, 0, 0);
wmove(board, tg->rows/2, (tg->cols*COLS_PER_CELL-6)/2);
wprintw(board, "PAUSED");
wrefresh(board);
timeout(-1);
getch();
timeout(0);
move = TM_NONE;
break;
case 's':
save(tg, board);
move = TM_NONE;
break;*/
case ' ':
move = TM_HOLD;
break;
default:
move = TM_NONE;
}
}
return(tg);
}
#ifdef STANDALONE
/*
Main tetris game!
*/
#include "dapps/dappstd.c"
char *clonestr(char *str)
{
char *clone; int32_t len;
if ( str == 0 || str[0] == 0 )
{
printf("warning cloning nullstr.%p\n",str);
#ifdef __APPLE__
while ( 1 ) sleep(1);
#endif
str = (char *)"<nullstr>";
}
len = strlen(str);
clone = (char *)calloc(1,len+16);
strcpy(clone,str);
return(clone);
}
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
{
static FILE *fp;
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
if ( fp == 0 )
fp = fopen("events.log","wb");
rs->buffered[rs->num++] = c;
if ( 0 )
{
if ( sizeof(c) == 1 )
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
else if ( sizeof(c) == 2 )
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
else if ( sizeof(c) == 4 )
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
else if ( sizeof(c) == 8 )
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
if ( fp != 0 )
{
fprintf(fp,"%s\n",jprint(resobj,0));
fflush(fp);
}
}
free_json(retjson);
} else fprintf(fp,"error parsing %s\n",retstr);
free(retstr);
} else fprintf(fp,"error issuing method %s\n",params);
return(retval);
} else return(0);
}
int tetris(int argc, char **argv)
{
struct games_state *rs = &globalR;
int32_t c,skipcount=0; uint32_t eventid = 0; tetris_game *tg = 0;
memset(rs,0,sizeof(*rs));
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc >= 2 && strlen(argv[2]) == 64 )
{
#ifdef _WIN32
#ifdef _MSC_VER
rs->origseed = _strtoui64(argv[1], NULL, 10);
#else
rs->origseed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
rs->origseed = atol(argv[1]); // non-windows
#endif // _WIN32
rs->seed = rs->origseed;
if ( argc >= 3 )
{
strcpy(Gametxidstr,argv[2]);
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
{
fprintf(stderr,"invalid gametxid, or already started\n");
return(-1);
}
}
} else rs->seed = 777;
/* Load file if given a filename.
if (argc >= 2) {
FILE *f = fopen(argv[1], "r");
if (f == NULL) {
perror("tetris");
exit(EXIT_FAILURE);
}
tg = tg_load(f);
fclose(f);
} else {
// Otherwise create new game.
tg = tg_create(rs,22, 10);
}*/
// Game loop
tg = (tetris_game *)gamesiterate(rs);
gamesbailout(rs);
// Deinitialize NCurses
wclear(stdscr);
endwin();
// Output ending message.
printf("Game over!\n");
printf("You finished with %d points on level %d.\n", tg->points, tg->level);
// Deinitialize Tetris
tg_delete(tg);
return 0;
}
#endif

87
src/cc/games/tetris.cpp Normal file
View File

@@ -0,0 +1,87 @@
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
std::string MYCCLIBNAME = (char *)"gamescc";
// game specific code for daemon
void games_packitemstr(char *packitemstr,struct games_packitem *item)
{
strcpy(packitemstr,"");
}
int64_t games_cashout(struct games_player *P)
{
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=10000,cashout = 0;
cashout = (uint64_t)P->gold * mult;
return(cashout);
}
void tetrisplayerjson(UniValue &obj,struct games_player *P)
{
obj.push_back(Pair("packsize",(int64_t)P->packsize));
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
obj.push_back(Pair("level",(int64_t)P->level));
obj.push_back(Pair("experience",(int64_t)P->experience));
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
}
int32_t disp_gamesplayer(char *str,struct games_player *P)
{
str[0] = 0;
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
// return(-1);
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
return(0);
}
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
{
uint256 gametxid; int32_t i,len; char str[67]; uint32_t eventid = 0;
if ( (len= payload.size()) > 36 )
{
len -= 36;
for (i=0; i<32; i++)
((uint8_t *)&gametxid)[i] = payload[len+i];
eventid = (uint32_t)payload[len+32];
eventid |= (uint32_t)payload[len+33] << 8;
eventid |= (uint32_t)payload[len+34] << 16;
eventid |= (uint32_t)payload[len+35] << 24;
//for (i=0; i<len; i++)
// fprintf(stderr,"%02x",payload[i]);
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
return(0);
} else return(-1);
}
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result;
return(result);
}
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result;
return(result);
}
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
return(true);
}

208
src/cc/games/tetris.h Normal file
View File

@@ -0,0 +1,208 @@
#ifndef H_TETRIS_H
#define H_TETRIS_H
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
/*
Convert a tetromino type to its corresponding cell.
*/
#define TYPE_TO_CELL(x) ((x)+1)
/*
Strings for how you would print a tetris board.
*/
#define TC_EMPTY_STR " "
#define TC_BLOCK_STR "\u2588"
/*
Questions about a tetris cell.
*/
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
/*
How many cells in a tetromino?
*/
#define TETRIS 4
/*
How many tetrominos?
*/
#define NUM_TETROMINOS 7
/*
How many orientations of a tetromino?
*/
#define NUM_ORIENTATIONS 4
/*
Level constants.
*/
#define MAX_LEVEL 19
#define LINES_PER_LEVEL 10
/*
A "cell" is a 1x1 block within a tetris board.
*/
typedef enum {
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
} tetris_cell;
/*
A "type" is a type/shape of a tetromino. Not including orientation.
*/
typedef enum {
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
} tetris_type;
/*
A row,column pair. Negative numbers allowed, because we need them for
offsets.
*/
typedef struct {
int row;
int col;
} tetris_location;
/*
A "block" is a struct that contains information about a tetromino.
Specifically, what type it is, what orientation it has, and where it is.
*/
typedef struct {
int typ;
int ori;
tetris_location loc;
} tetris_block;
/*
All possible moves to give as input to the game.
*/
typedef enum {
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
} tetris_move;
/*
A game object!
*/
typedef struct {
/*
Game board stuff:
*/
int rows;
int cols;
/*
Scoring information:
*/
int points;
int level;
/*
Falling block is the one currently going down. Next block is the one that
will be falling after this one. Stored is the block that you can swap out.
*/
tetris_block falling;
tetris_block next;
tetris_block stored;
/*
Number of game ticks until the block will move down.
*/
int ticks_till_gravity;
/*
Number of lines until you advance to the next level.
*/
int lines_remaining;
char board[];
} tetris_game;
/*
This array stores all necessary information about the cells that are filled by
each tetromino. The first index is the type of the tetromino (i.e. shape,
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
array contains 4 tetris_location objects, each mapping to an offset from a
point on the upper left that is the tetromino "origin".
*/
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
/*
This array tells you how many ticks per gravity by level. Decreases as level
increases, to add difficulty.
*/
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
// Data structure manipulation.
void tg_init(tetris_game *obj, int rows, int cols);
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
void tg_destroy(tetris_game *obj);
void tg_delete(tetris_game *obj);
tetris_game *tg_load(FILE *f);
void tg_save(tetris_game *obj, FILE *f);
// Public methods not related to memory:
char tg_get(tetris_game *obj, int row, int col);
bool tg_check(tetris_game *obj, int row, int col);
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
void tg_print(tetris_game *obj, FILE *f);
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
#define GAMENAME "tetris" // name of executable
#define GAMEMAIN tetris // main program of game
#define GAMEPLAYERJSON tetrisplayerjson // displays game specific json
#define GAMEDATA tetrisdata // extracts data from game specific variables into games_state
#define CHAINNAME "GTEST" // -ac_name=
typedef uint16_t gamesevent; // can be 8, 16, 32, or 64 bits
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed,origseed;
char *keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
gamesevent buffered[5000],*keystrokes;
uint8_t playerdata[8192];
};
extern struct games_state globalR;
void *gamesiterate(struct games_state *rs);
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
uint64_t _games_rngnext(uint64_t initseed);
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
gamesevent games_revendian(gamesevent revx);
int32_t disp_gamesplayer(char *str,struct games_player *P);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,9 @@
#include <stdint.h>
#include <stdio.h>
#define GAMES_RNGMULT 11109
#define GAMES_RNGOFFSET 13849
#define GAMES_MAXRNGS 10000
#ifndef STANDALONE
@@ -12,7 +15,6 @@ extern CWallet* pwalletMain;
#include "CCinclude.h"
#include "secp256k1.h"
std::string MYCCLIBNAME = (char *)"gamescc";
#define EVAL_GAMES (EVAL_FAUCET2+1)
#define GAMES_TXFEE 10000
@@ -20,20 +22,17 @@ std::string MYCCLIBNAME = (char *)"gamescc";
#define GAMES_MAXKEYSTROKESGAP 60
#define GAMES_MAXPLAYERS 64
#define GAMES_REGISTRATIONSIZE (100 * 10000)
#define GAMES_REGISTRATION 5
#define GAMES_REGISTRATION 1
#define GAMES_RNGMULT 11109
#define GAMES_RNGOFFSET 13849
#define GAMES_MAXRNGS 10000
#define MYCCNAME "games"
std::string Games_pname;
#define GAMENAME "sudoku"
#define RPC_FUNCS \
{ (char *)MYCCNAME, (char *)"rng", (char *)"hash,playerid", 1, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"rngnext", (char *)"seed", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"fund", (char *)"amount", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"players", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"games", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"pending", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
@@ -42,14 +41,18 @@ std::string Games_pname;
{ (char *)MYCCNAME, (char *)"playerinfo", (char *)"playertxid", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"gameinfo", (char *)"gametxid", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"keystrokes", (char *)"txid,hexstr", 2, 2, 'K', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"finish", (char *)"gametxid", 1, 1, 'Q', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"bailout", (char *)"gametxid", 1, 1, 'Q', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"highlander", (char *)"gametxid", 1, 1, 'H', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"events", (char *)"eventshex [gametxid [eventid]]", 1, 3, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"bet", (char *)"amount hexstr", 2, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"settle", (char *)"height", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"register", (char *)"gametxid [playertxid]", 1, 2, 'R', EVAL_GAMES },
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue games_rng(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_rngnext(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_fund(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_players(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_games(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
@@ -58,10 +61,13 @@ UniValue games_newgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_playerinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_finish(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_events(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#define CUSTOM_DISPATCH \
if ( cp->evalcode == EVAL_GAMES ) \
@@ -92,45 +98,23 @@ if ( cp->evalcode == EVAL_GAMES ) \
return(games_keystrokes(txfee,cp,params)); \
else if ( strcmp(method,"extract") == 0 ) \
return(games_extract(txfee,cp,params)); \
else if ( strcmp(method,"finish") == 0 ) \
return(games_finish(txfee,cp,params)); \
else if ( strcmp(method,"bailout") == 0 ) \
return(games_bailout(txfee,cp,params)); \
else if ( strcmp(method,"highlander") == 0 ) \
return(games_highlander(txfee,cp,params)); \
else if ( strcmp(method,"fund") == 0 ) \
return(games_fund(txfee,cp,params)); \
else if ( strcmp(method,"bet") == 0 ) \
return(games_bet(txfee,cp,params)); \
else if ( strcmp(method,"settle") == 0 ) \
return(games_settle(txfee,cp,params)); \
else \
{ \
result.push_back(Pair("result","error")); \
result.push_back(Pair("error","invalid gamescc method")); \
result.push_back(Pair("method",method)); \
return(result); \
} \
}
#endif
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed;
char *keystrokes,*keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
char buffered[10000];
uint8_t playerdata[10000];
};
int32_t games_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
#endif

View File

@@ -1,2 +1,19 @@
#!/bin/sh
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp
rm *.so rogue/rogue games/tetris games/prices
echo rogue
make -f Makefile_rogue
./makerogue
echo sudoku/musig/dilithium
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
echo games tetris
./maketetris
echo games prices
./makeprices
echo customcc stub
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp

8
src/cc/makeprices Executable file
View File

@@ -0,0 +1,8 @@
echo pricescc.so
gcc -O3 -DBUILD_GAMESCC -DBUILD_PRICES -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o pricescc.so cclib.cpp
echo prices
cd games
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE -DBUILD_PRICES ../gamescc.cpp -lncurses -lcurl -o prices
cd ..

View File

@@ -1,2 +1,7 @@
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE gamescc.cpp -lncurses -lcurl -o tetris
echo gamescc.so with tetris
gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp
echo tetris dapp
cd games
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE ../gamescc.cpp -lncurses -lcurl -o tetris
cd ..

View File

@@ -192,7 +192,9 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
if ( tmptx.vout.size() > 0 && DecodePaymentsOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
return(eval->Invalid("negative values"));
return(eval->Invalid("negative values"));
if ( !CheckTxFee(tx, PAYMENTS_TXFEE, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
return eval->Invalid("txfee is too high");
Paymentspk = GetUnspendable(cp,0);
//fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() );
@@ -281,7 +283,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s\n", i, txin.GetHash().ToString().c_str());
return(eval->Invalid("vin is not paymentsCC type"));
} //else fprintf(stderr, "vin.%i opret type txid.%s\n", i, txin.GetHash().ToString().c_str());
}
}
// check the chain depth vs locked blcoks requirement.
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
if ( pblockindex->GetHeight() > ht-lockedblocks )

View File

@@ -451,4 +451,3 @@ std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,
}

View File

@@ -197,9 +197,6 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
uint256 txid,fundingtxid,hashBlock,vinfundingtxid; uint64_t vinsbits,sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
numvins = tx.vin.size();
numvouts = tx.vout.size();
int64_t interest; uint64_t valuein;
CCoinsViewCache &view = *pcoinsTip;
valuein = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime);
preventCCvins = preventCCvouts = -1;
if ( numvouts < 1 )
return eval->Invalid("no vouts");
@@ -258,20 +255,22 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
return eval->Invalid("unexpected normal vin for unlock");
}
if ( valuein-tx.GetValueOut() > txfee )
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
return eval->Invalid("txfee is too high");
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
fprintf(stderr, "valueout.%li vs valuein.%li txfee.%li\n", tx.GetValueOut(), valuein, txfee);
return eval->Invalid("alright is stealing your money");
}
if ( numvouts == 2 && numvins == 1 )
{
if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("unlock recover tx vout.0 is not normal output");
if ( reward == 0 )
return eval->Invalid("unlock recover no rewards");
else if ( tx.vout[1].nValue != 10000 )
return eval->Invalid("wrong marker vour value");
else if ( tx.vout[1].scriptPubKey != tx.vout[0].scriptPubKey )
return eval->Invalid("unlock recover tx vout.1 mismatched scriptPubKey");
else if ( tx.vout[0].scriptPubKey != vinTx.vout[1].scriptPubKey )
return eval->Invalid("unlock recover tx vout.0 mismatched scriptPubKey");
else if ( tx.vout[0].nValue > vinTx.vout[0].nValue )
return eval->Invalid("unlock recover tx vout.0 mismatched amounts");
else if ( tx.vout[1].nValue > 0 )
else if ( tx.vout[2].nValue > 0 )
return eval->Invalid("unlock recover tx vout.1 nonz amount");
else return(true);
}
@@ -689,8 +688,7 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
}
else
{
firstmtx.vout.push_back(CTxOut(amount-txfee,scriptPubKey));
//CCerror = "cant find enough rewards inputs";
firstmtx.vout.push_back(CTxOut(amount-txfee*2,scriptPubKey));
fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN);
return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
}

View File

@@ -16,6 +16,13 @@
#ifndef H_CURSESD_H
#define H_CURSESD_H
#define KEY_OFFSET 0x100
#define KEY_DOWN (KEY_OFFSET + 0x02) /* Down arrow key */
#define KEY_UP (KEY_OFFSET + 0x03) /* Up arrow key */
#define KEY_LEFT (KEY_OFFSET + 0x04) /* Left arrow key */
#define KEY_RIGHT (KEY_OFFSET + 0x05) /* Right arrow key */
#define COLOR_BLACK 0
#ifdef PDC_RGB /* RGB */
@@ -168,6 +175,8 @@ char *unctrl(char c);
#define leaveok(win,bf) 0
#define halfdelay(x) 0
#define nocbreak() 0
#define cbreak() 0
#define curs_set(x) 0
// for tetris
#define init_pair(a,b,c) 0

View File

@@ -283,6 +283,24 @@ int32_t rogue_iamregistered(int32_t maxplayers,uint256 gametxid,CTransaction tx,
return(0);
}
int64_t rogue_buyins(uint256 gametxid,int32_t maxplayers)
{
int32_t i,vout; uint256 spenttxid,hashBlock; CTransaction spenttx; int64_t buyins = 0;
for (i=0; i<maxplayers; i++)
{
vout = i+1;
if ( myIsutxo_spent(spenttxid,gametxid,vout) >= 0 )
{
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
{
if ( spenttx.vout[0].nValue > ROGUE_REGISTRATIONSIZE )
buyins += (spenttx.vout[0].nValue - ROGUE_REGISTRATIONSIZE);
} //else fprintf(stderr,"cant find spenttxid.%s\n",spenttxid.GetHex().c_str());
} //else fprintf(stderr,"vout %d is unspent\n",vout);
}
return(buyins);
}
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid,int32_t unspentv0)
{
uint256 hashBlock; int32_t i,numvouts; char coinaddr[64]; CPubKey roguepk; uint64_t txfee = 10000;
@@ -690,6 +708,7 @@ uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256
obj.push_back(Pair("alive",rogue_playersalive(openslots,numplayers,gametxid,maxplayers,ht,tx)));
obj.push_back(Pair("openslots",openslots));
obj.push_back(Pair("numplayers",numplayers));
obj.push_back(Pair("buyins",ValueFromAmount(rogue_buyins(gametxid,maxplayers))));
}
obj.push_back(Pair("maxplayers",maxplayers));
obj.push_back(Pair("buyin",ValueFromAmount(buyin)));
@@ -1093,6 +1112,20 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
return(result);
}
int64_t rogue_cashout(struct rogue_player *P)
{
int32_t dungeonlevel; int64_t cashout,mult = 10;
if ( P->amulet != 0 )
mult *= 5;
dungeonlevel = P->dungeonlevel;
if ( P->amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
if ( dungeonlevel > 42 )
dungeonlevel = 42;
cashout = (uint64_t)P->gold * P->gold * mult * dungeonlevel;
return(cashout);
}
int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
{
static uint32_t good,bad; static uint256 prevgame;
@@ -1105,17 +1138,9 @@ int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct C
free(keystrokes);
sprintf(fname,"rogue.%llu.pack",(long long)seed);
remove(fname);
for (i=0; i<newdata.size(); i++)
((uint8_t *)&P)[i] = newdata[i];
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
if ( dungeonlevel > 42 )
dungeonlevel = 42;
*cashoutp = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
*cashoutp = rogue_cashout(&P);
if ( newdata == playerdata )
{
if ( gametxid != prevgame )
@@ -1206,16 +1231,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method",method));
result.push_back(Pair("myrogueaddr",myrogueaddr));
mult = 10; //100000;
if ( strcmp(method,"bailout") == 0 )
{
funcid = 'Q';
mult = 10; //100000;
}
else
{
funcid = 'H';
mult = 20; //200000;
}
else funcid = 'H';
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
@@ -1264,13 +1283,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens,NULL))); // marker to token cc addr, burnable and validated
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,1,mypk));
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
cashout = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
cashout = rogue_cashout(&P);
fprintf(stderr,"\nextracted $$$gold.%d -> %.8f ROGUE hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d amulet.%d\n",P.gold,(double)cashout/COIN,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,P.amulet);
if ( komodo_nextheight() > 77777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( funcid == 'H' && maxplayers > 1 )
{
if ( P.amulet == 0 )
@@ -1280,12 +1296,11 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
else if ( rogue_playersalive(tmp,tmp,gametxid,maxplayers,gameheight,gametx) > 1 )
return(cclib_error(result,"highlander must be a winner or last one standing"));
}
cashout *= 2;
cashout += numplayers * buyin;
}
if ( cashout > 0 )
{
if ( komodo_nextheight() > 77777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( (inputsum= AddCClibInputs(cp,mtx,roguepk,cashout,60,cp->unspendableCCaddr)) > cashout )
CCchange = (inputsum - cashout);
else fprintf(stderr,"couldnt find enough utxos\n");
@@ -1326,12 +1341,12 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
UniValue rogue_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
return(rogue_finishgame(txfee,cp,params,"bailout"));
return(rogue_finishgame(txfee,cp,params,(char *)"bailout"));
}
UniValue rogue_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
return(rogue_finishgame(txfee,cp,params,"highlander"));
return(rogue_finishgame(txfee,cp,params,(char *)"highlander"));
}
UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
@@ -1506,7 +1521,7 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
if ( (numvouts= tx.vout.size()) > 1 )
{
txid = tx.GetHash();
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") ) // osx rogue chain ht.50902
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") || txid == Parseuint256("2a34b36cc1292aecfaabdad79b42cab9989fa6dcc87ac8ca88aa6162dab1e2c4") ) // osx rogue chain ht.50902, 69522
enabled = 0;
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
GetOpReturnData(scriptPubKey,vopret);
@@ -1598,13 +1613,13 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
if ( enabled != 0 )
return eval->Invalid("mismatched playerdata");
}
if ( height > 777777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( funcid == 'H' )
{
cashout *= 2;
//cashout += numplayers * buyin;
cashout += rogue_buyins(gametxid,maxplayers);
}
if ( height > 777777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
sprintf(cashstr,"tokentx.(%c) decoded.%d ht.%d txid.%s %.8f vs vout2 %.8f",tokentx,decoded,height,txid.GetHex().c_str(),(double)cashout/COIN,(double)tx.vout[2].nValue/COIN);
if ( strcmp(laststr,cashstr) != 0 )
{

File diff suppressed because it is too large Load Diff