Prices example
This commit is contained in:
@@ -14,7 +14,11 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "gamescc.h"
|
#include "gamescc.h"
|
||||||
#include "tetris.c" // replace with game code
|
#ifdef BUILD_PRICES
|
||||||
|
#include "prices.c"
|
||||||
|
#elif
|
||||||
|
#include "tetris.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
int32_t GAMEDATA(struct games_player *P,void *ptr);
|
int32_t GAMEDATA(struct games_player *P,void *ptr);
|
||||||
|
|
||||||
@@ -161,8 +165,11 @@ int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int3
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
|
#ifdef BUILD_PRICES
|
||||||
#include "tetris.cpp" // replace with game specific functions
|
#include "prices.cpp"
|
||||||
|
#elif
|
||||||
|
#include "tetris.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
void GAMEJSON(UniValue &obj,struct games_player *P);
|
void GAMEJSON(UniValue &obj,struct games_player *P);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ echo games 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
|
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
|
||||||
./maketetris
|
./maketetris
|
||||||
|
|
||||||
|
echo games prices
|
||||||
|
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
|
||||||
|
./makeprices
|
||||||
|
|
||||||
echo customcc stub
|
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
|
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
|
||||||
|
|
||||||
|
|||||||
896
src/cc/prices.c
Normal file
896
src/cc/prices.c
Normal file
@@ -0,0 +1,896 @@
|
|||||||
|
|
||||||
|
#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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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]\"]",c&0xff,gametxidstr,eventid);
|
||||||
|
else if ( sizeof(c) == 2 )
|
||||||
|
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",c&0xffff,gametxidstr,eventid);
|
||||||
|
else if ( sizeof(c) == 4 )
|
||||||
|
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",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
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||||
* *
|
* *
|
||||||
@@ -13,442 +14,60 @@
|
|||||||
* *
|
* *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "CCassets.h"
|
// game specific code for daemon
|
||||||
#include "CCPrices.h"
|
void games_packitemstr(char *packitemstr,struct games_packitem *item)
|
||||||
|
|
||||||
/*
|
|
||||||
Prices CC would best build on top of the oracles CC, ie. to combine payments for multiple oracles and to calculate a 51% protected price feed.
|
|
||||||
|
|
||||||
We need to assume there is an oracle for a specific price. In the event there are more than one provider, the majority need to be within correlation distance to update a pricepoint.
|
|
||||||
|
|
||||||
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
|
|
||||||
|
|
||||||
Using the above function, a consensus price can be obtained for a datasource.
|
|
||||||
|
|
||||||
given an oracletxid, the marketaddr and format can be extracted to be used for future calls to OraclePrice. This allows to set a starting price and that in turn allows cash settled leveraged trading!
|
|
||||||
|
|
||||||
Funds work like with dice, ie. there is a Prices plan that traders bet against.
|
|
||||||
|
|
||||||
PricesFunding oracletxid, margin, priceaveraging, maxleverage, funding, longtoken, shorttoken, N [pubkeys]
|
|
||||||
|
|
||||||
PricesBet -> oracletxid start with 'L', leverage, funding, direction
|
|
||||||
funds are locked into global CC address
|
|
||||||
it can be closed at anytime by the trader for cash settlement
|
|
||||||
the house account can close it if rekt
|
|
||||||
|
|
||||||
Implementation Notes:
|
|
||||||
In order to eliminate the need for worrying about sybil attacks, each prices plan would be able to specific pubkey(s?) for whitelisted publishers. It would be possible to have a non-whitelisted plan that would use 50% correlation between publishers.
|
|
||||||
|
|
||||||
delta neutral balancing of riskexposure: fabs(long exposure - short exposure)
|
|
||||||
bet +B at leverage L
|
|
||||||
absval(sum(+BLi) - sum(-Bli))
|
|
||||||
|
|
||||||
validate: update riskexposure and it needs to be <= funds
|
|
||||||
|
|
||||||
PricesProfits: limit withdraw to funds in excess of riskexposure
|
|
||||||
PricesFinish: payout (if winning) and update riskexposure
|
|
||||||
need long/short exposure assets
|
|
||||||
|
|
||||||
funding -> 1of2 CC global CC address and dealer address, exposure tokens to global 1of2 assets CC address
|
|
||||||
pricebet -> user funds and exposure token to 1of2 address.
|
|
||||||
pricewin -> winnings from dealer funds, exposure token back to global address
|
|
||||||
priceloss -> exposuretoken back to global address
|
|
||||||
|
|
||||||
exposure address, funds address
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// start of consensus code
|
|
||||||
|
|
||||||
int64_t PricesOraclePrice(int64_t &rektprice,uint64_t mode,uint256 oracletxid,std::vector<CPubKey>pubkeys,int32_t dir,int64_t amount,int32_t leverage)
|
|
||||||
{
|
{
|
||||||
int64_t price;
|
strcpy(packitemstr,"");
|
||||||
// howto ensure price when block it confirms it not known
|
|
||||||
// get price from oracle + current chaintip
|
|
||||||
// normalize leveraged amount
|
|
||||||
if ( dir > 0 )
|
|
||||||
rektprice = price * leverage / (leverage-1);
|
|
||||||
else rektprice = price * (leverage-1) / leverage;
|
|
||||||
return(price);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript EncodePricesFundingOpRet(uint8_t funcid,CPubKey planpk,uint256 oracletxid,uint256 longtoken,uint256 shorttoken,int32_t millimargin,uint64_t mode,int32_t maxleverage,std::vector<CPubKey> pubkeys,uint256 bettoken)
|
int64_t games_cashout(struct games_player *P)
|
||||||
{
|
{
|
||||||
CScript opret;
|
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=1000,cashout = 0;
|
||||||
fprintf(stderr,"implement EncodePricesFundingOpRet\n");
|
cashout = (uint64_t)P->gold * mult * dungeonlevel * dungeonlevel;
|
||||||
return(opret);
|
return(cashout);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DecodePricesFundingOpRet(CScript scriptPubKey,CPubKey &planpk,uint256 &oracletxid,uint256 &longtoken,uint256 &shorttoken,int32_t &millimargin,uint64_t &mode,int32_t &maxleverage,std::vector<CPubKey> &pubkeys,uint256 &bettoken)
|
void tetrisplayerjson(UniValue &obj,struct games_player *P)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"implement DecodePricesFundingOpRet\n");
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
|
||||||
{
|
{
|
||||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
uint256 gametxid; int32_t i,len; char str[67]; uint32_t eventid = 0;
|
||||||
|
if ( (len= payload.size()) > 36 )
|
||||||
return true; // TODO remove, for test dual-evals
|
|
||||||
|
|
||||||
return eval->Invalid("no validation yet");
|
|
||||||
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
|
|
||||||
numvins = tx.vin.size();
|
|
||||||
numvouts = tx.vout.size();
|
|
||||||
preventCCvins = preventCCvouts = -1;
|
|
||||||
if ( numvouts < 1 )
|
|
||||||
return eval->Invalid("no vouts");
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (i=0; i<numvins; i++)
|
len -= 36;
|
||||||
{
|
for (i=0; i<32; i++)
|
||||||
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
|
((uint8_t *)&gametxid)[i] = payload[len+i];
|
||||||
{
|
eventid = (uint32_t)payload[len+32];
|
||||||
return eval->Invalid("illegal normal vini");
|
eventid |= (uint32_t)payload[len+33] << 8;
|
||||||
}
|
eventid |= (uint32_t)payload[len+34] << 16;
|
||||||
}
|
eventid |= (uint32_t)payload[len+35] << 24;
|
||||||
//fprintf(stderr,"check amounts\n");
|
//for (i=0; i<len; i++)
|
||||||
//if ( PricesExactAmounts(cp,eval,tx,1,10000) == false )
|
// 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);
|
||||||
fprintf(stderr,"Pricesget invalid amount\n");
|
return(0);
|
||||||
return false;
|
} else return(-1);
|
||||||
}
|
|
||||||
//else
|
|
||||||
{
|
|
||||||
txid = tx.GetHash();
|
|
||||||
memcpy(hash,&txid,sizeof(hash));
|
|
||||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
|
||||||
if ( retval != 0 )
|
|
||||||
fprintf(stderr,"Pricesget validated\n");
|
|
||||||
else fprintf(stderr,"Pricesget invalid\n");
|
|
||||||
return(retval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end of consensus code
|
|
||||||
|
|
||||||
// helper functions for rpc calls in rpcwallet.cpp
|
|
||||||
|
|
||||||
int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char *destaddr,uint256 tolenid,int64_t total,int32_t maxinputs)
|
|
||||||
{
|
|
||||||
// add threshold check
|
|
||||||
int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
|
|
||||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
|
||||||
SetCCunspents(unspentOutputs,destaddr);
|
|
||||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
|
||||||
{
|
|
||||||
txid = it->first.txhash;
|
|
||||||
vout = (int32_t)it->first.index;
|
|
||||||
// need to prevent dup
|
|
||||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && vout < vintx.vout.size() )
|
|
||||||
{
|
|
||||||
// need to verify assetid
|
|
||||||
if ( (nValue= vintx.vout[vout].nValue) >= 10000 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
|
|
||||||
{
|
|
||||||
if ( total != 0 && maxinputs != 0 )
|
|
||||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
|
||||||
nValue = it->second.satoshis;
|
|
||||||
totalinputs += nValue;
|
|
||||||
n++;
|
|
||||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(totalinputs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue PricesList()
|
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||||
{
|
{
|
||||||
UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint64_t mode; int32_t margin,maxleverage; std::vector<CPubKey>pubkeys; uint256 txid,hashBlock,oracletxid,longtoken,shorttoken,bettoken; CPubKey planpk,pricespk; char str[65]; CTransaction vintx;
|
return(true);
|
||||||
cp = CCinit(&C,EVAL_PRICES);
|
|
||||||
pricespk = GetUnspendable(cp,0);
|
|
||||||
SetCCtxids(addressIndex,cp->normaladdr);
|
|
||||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
|
|
||||||
{
|
|
||||||
txid = it->first.txhash;
|
|
||||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
|
||||||
{
|
|
||||||
if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' )
|
|
||||||
{
|
|
||||||
result.push_back(uint256_str(str,txid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// longtoken satoshis limits long exposure
|
|
||||||
// shorttoken satoshis limits short exposure
|
|
||||||
// both must be in the 1of2 CC address with its total supply
|
|
||||||
// bettoken
|
|
||||||
std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector<CPubKey> pubkeys)
|
|
||||||
{
|
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
|
||||||
CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C;
|
|
||||||
if ( funding < 100*COIN || maxleverage <= 0 || maxleverage > 10000 )
|
|
||||||
{
|
|
||||||
CCerror = "invalid parameter error";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
cp = CCinit(&C,EVAL_PRICES);
|
|
||||||
if ( txfee == 0 )
|
|
||||||
txfee = 10000;
|
|
||||||
mypk = pubkey2pk(Mypubkey());
|
|
||||||
pricespk = GetUnspendable(cp,0);
|
|
||||||
if ( (N= (int32_t)pubkeys.size()) || N > 15 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"too many pubkeys N.%d\n",N);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
for (i=0; i<N; i++)
|
|
||||||
{
|
|
||||||
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pubkeys[i])) << OP_CHECKSIG);
|
|
||||||
if ( CCaddress_balance(coinaddr) == 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"N.%d but pubkeys[%d] has no balance\n",N,i);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( GetCCaddress1of2(cp,houseaddr,pricespk,mypk) == 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"PricesCreateFunding cant create globaladdr\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( CCtoken_balance(houseaddr,longtoken) != CCfullsupply(longtoken) )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(longtoken)/COIN);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( CCtoken_balance(houseaddr,shorttoken) != CCfullsupply(shorttoken) )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"PricesCreateFunding (%s) globaladdr.%s token balance %.8f != %.8f\n",uint256_str(str,longtoken),houseaddr,(double)CCtoken_balance(houseaddr,longtoken)/COIN,(double)CCfullsupply(shorttoken)/COIN);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= oracletx.vout.size()) <= 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find oracletxid %s\n",uint256_str(str,oracletxid));
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
fprintf(stderr,"error check bettoken\n");
|
|
||||||
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 )
|
|
||||||
{
|
|
||||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
|
||||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG));
|
|
||||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesFundingOpRet('F',mypk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CCerror = "cant find enough inputs";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
}
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
|
|
||||||
UniValue PricesInfo(uint256 fundingtxid)
|
|
||||||
{
|
|
||||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR); CPubKey pricespk,planpk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction vintx; int64_t balance,supply,exposure; uint64_t funding,mode; int32_t i,margin,maxleverage; char numstr[65],houseaddr[64],exposureaddr[64],str[65]; std::vector<CPubKey>pubkeys; struct CCcontract_info *cp,C;
|
|
||||||
cp = CCinit(&C,EVAL_PRICES);
|
|
||||||
pricespk = GetUnspendable(cp,0);
|
|
||||||
if ( GetTransaction(fundingtxid,vintx,hashBlock,false) == 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find fundingtxid\n");
|
|
||||||
ERR_RESULT("cant find fundingtxid");
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
if ( vintx.vout.size() > 0 && DecodePricesFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' )
|
|
||||||
{
|
|
||||||
result.push_back(Pair("result","success"));
|
|
||||||
result.push_back(Pair("fundingtxid",uint256_str(str,fundingtxid)));
|
|
||||||
result.push_back(Pair("bettoken",uint256_str(str,bettoken)));
|
|
||||||
result.push_back(Pair("oracletxid",uint256_str(str,oracletxid)));
|
|
||||||
sprintf(numstr,"%.3f",(double)margin/1000);
|
|
||||||
result.push_back(Pair("profitmargin",numstr));
|
|
||||||
result.push_back(Pair("maxleverage",maxleverage));
|
|
||||||
result.push_back(Pair("mode",(int64_t)mode));
|
|
||||||
for (i=0; i<pubkeys.size(); i++)
|
|
||||||
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
|
|
||||||
result.push_back(Pair("pubkeys",a));
|
|
||||||
GetCCaddress1of2(cp,houseaddr,pricespk,planpk);
|
|
||||||
GetCCaddress1of2(cp,exposureaddr,pricespk,pricespk); // assets addr
|
|
||||||
result.push_back(Pair("houseaddr",houseaddr));
|
|
||||||
result.push_back(Pair("betaddr",exposureaddr));
|
|
||||||
result.push_back(Pair("longtoken",uint256_str(str,longtoken)));
|
|
||||||
supply = CCfullsupply(longtoken);
|
|
||||||
result.push_back(Pair("longsupply",supply));
|
|
||||||
balance = CCtoken_balance(houseaddr,longtoken);
|
|
||||||
result.push_back(Pair("longavail",balance));
|
|
||||||
exposure = CCtoken_balance(exposureaddr,longtoken);
|
|
||||||
result.push_back(Pair("longexposure",exposure));
|
|
||||||
result.push_back(Pair("shorttoken",uint256_str(str,shorttoken)));
|
|
||||||
supply = CCfullsupply(shorttoken);
|
|
||||||
result.push_back(Pair("shortsupply",supply));
|
|
||||||
balance = CCtoken_balance(houseaddr,shorttoken);
|
|
||||||
result.push_back(Pair("shortavail",balance));
|
|
||||||
exposure = CCtoken_balance(exposureaddr,shorttoken);
|
|
||||||
result.push_back(Pair("shortexposure",exposure));
|
|
||||||
sprintf(numstr,"%.8f",(double)CCtoken_balance(houseaddr,bettoken)/COIN);
|
|
||||||
result.push_back(Pair("funds",numstr));
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount)
|
|
||||||
{
|
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
|
||||||
struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,CCchange = 0; uint64_t funding,mode; int32_t margin,maxleverage; char houseaddr[64],myaddr[64]; std::vector<CPubKey>pubkeys;
|
|
||||||
if ( amount < 10000 )
|
|
||||||
{
|
|
||||||
CCerror = "amount must be positive";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
cp = CCinit(&C,EVAL_PRICES);
|
|
||||||
if ( txfee == 0 )
|
|
||||||
txfee = 10000;
|
|
||||||
mypk = pubkey2pk(Mypubkey());
|
|
||||||
pricespk = GetUnspendable(cp,0);
|
|
||||||
GetCCaddress(cp,myaddr,mypk);
|
|
||||||
if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find fundingtxid\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken )
|
|
||||||
{
|
|
||||||
GetCCaddress1of2(cp,houseaddr,pricespk,planpk);
|
|
||||||
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
|
|
||||||
{
|
|
||||||
if ( (inputs= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,60)) >= amount )
|
|
||||||
{
|
|
||||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk));
|
|
||||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(planpk)) << OP_CHECKSIG));
|
|
||||||
if ( inputs > amount+txfee )
|
|
||||||
CCchange = (inputs - amount);
|
|
||||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk));
|
|
||||||
// add addr2
|
|
||||||
|
|
||||||
std::vector<CPubKey> voutTokenPubkeysEmpty; //TODO: add token vout pubkeys
|
|
||||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,
|
|
||||||
EncodeTokenOpRet(bettoken, voutTokenPubkeysEmpty,
|
|
||||||
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey())))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CCerror = "cant find enough bet inputs";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CCerror = "cant find enough inputs";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount,int32_t leverage)
|
|
||||||
{
|
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
|
||||||
struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vector<CPubKey>pubkeys;
|
|
||||||
if ( amount < 0 )
|
|
||||||
{
|
|
||||||
amount = -amount;
|
|
||||||
dir = -1;
|
|
||||||
} else dir = 1;
|
|
||||||
cp = CCinit(&C,EVAL_PRICES);
|
|
||||||
if ( txfee == 0 )
|
|
||||||
txfee = 10000;
|
|
||||||
mypk = pubkey2pk(Mypubkey());
|
|
||||||
pricespk = GetUnspendable(cp,0);
|
|
||||||
GetCCaddress(cp,myaddr,mypk);
|
|
||||||
if ( GetTransaction(fundingtxid,tx,hashBlock,false) == 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find fundingtxid\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( tx.vout.size() > 0 && DecodePricesFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,planpk,oracletxid,longtoken,shorttoken,margin,mode,maxleverage,pubkeys,bettoken) == 'F' && bettoken == refbettoken )
|
|
||||||
{
|
|
||||||
if ( leverage > maxleverage || leverage < 1 )
|
|
||||||
{
|
|
||||||
fprintf(stderr,"illegal leverage\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
GetCCaddress1of2(cp,houseaddr,pricespk,planpk);
|
|
||||||
GetCCaddress1of2(cp,exposureaddr,pricespk,pricespk);
|
|
||||||
if ( dir < 0 )
|
|
||||||
tokenid = shorttoken;
|
|
||||||
else tokenid = longtoken;
|
|
||||||
exposure = leverage * amount;
|
|
||||||
longexposure = CCtoken_balance(exposureaddr,longtoken);
|
|
||||||
shortexposure = CCtoken_balance(exposureaddr,shorttoken);
|
|
||||||
netexposure = (longexposure - shortexposure + exposure*dir);
|
|
||||||
if ( netexposure < 0 )
|
|
||||||
netexposure = -netexposure;
|
|
||||||
balance = CCtoken_balance(myaddr,bettoken) / COIN;
|
|
||||||
if ( balance < netexposure*9/10 ) // 10% extra room for dynamically closed bets in wrong direction
|
|
||||||
{
|
|
||||||
fprintf(stderr,"balance %lld < 90%% netexposure %lld, refuse bet\n",(long long)balance,(long long)netexposure);
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
|
|
||||||
{
|
|
||||||
if ( (inputs= AddTokensInputs(cp,mtx,houseaddr,tokenid,exposure,30)) >= exposure )
|
|
||||||
{
|
|
||||||
if ( (inputs2= AddTokensInputs(cp,mtx,myaddr,bettoken,amount,30)) >= amount )
|
|
||||||
{
|
|
||||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,amount,pricespk,planpk));
|
|
||||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,exposure,pricespk,pricespk));
|
|
||||||
if ( inputs > exposure+txfee )
|
|
||||||
CCchange = (inputs - exposure);
|
|
||||||
if ( inputs2 > amount+txfee )
|
|
||||||
CCchange2 = (inputs2 - amount);
|
|
||||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,CCchange,pricespk,planpk));
|
|
||||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange2,mypk));
|
|
||||||
// add addr2 and addr3
|
|
||||||
//return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePricesExtra('T',tokenid,bettoken,zeroid,dir*leverage)));
|
|
||||||
CScript opret;
|
|
||||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find enough bettoken inputs\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr,"cant find enough exposure inputs\n");
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CCerror = "cant find enough inputsB";
|
|
||||||
fprintf(stderr,"%s\n", CCerror.c_str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
|
|
||||||
UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid)
|
|
||||||
{
|
|
||||||
UniValue result(UniValue::VOBJ);
|
|
||||||
// get height of bettxid
|
|
||||||
// get price and rekt
|
|
||||||
// get current height and price
|
|
||||||
// what about if rekt in the past?
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid)
|
|
||||||
{
|
|
||||||
return("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
208
src/cc/prices.h
Normal file
208
src/cc/prices.h
Normal 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
|
||||||
|
|
||||||
Reference in New Issue
Block a user