Guest User

Untitled

a guest
Nov 21st, 2018
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.24 KB | None | 0 0
  1. const fs = require('fs');
  2. const ACCOUNTS = require('./ACCOUNTS.json');
  3. const CONFIG = require('./CONFIG.json');
  4. const STRATEGY = require('./STRATEGY.json');
  5. const POKER_CONTRACT = 'eospokerwins';
  6.  
  7. const verboseLog = false;
  8.  
  9. /* ==== Record and regularly print out total earning of all accounts ==== */
  10. let totalWagered = 0;
  11. let totalEarning = 0;
  12. let totalHandPlayed = 0;
  13. setInterval(() => {
  14. console.log(`------ Earnings / House Edge (${totalHandPlayed} Hands) ------`);
  15. const printTxt = `${totalEarning.toFixed(4)} EOS / ${-(totalEarning / totalWagered * 100).toFixed(4)}%`;
  16. console.log(printTxt);
  17. fs.appendFileSync('poker-log.txt', `${printTxt}\n`, 'utf8');
  18. }, 600000);
  19.  
  20. /* ==== Start all accounts, will continue unfinished games automatically ==== */
  21. Object.keys(ACCOUNTS).forEach((name, index) => {
  22. setTimeout(() => playPoker(name), index * 2000);
  23. });
  24.  
  25. /* ==== Transfer all POKER to collectorAccount regularly ==== */
  26. setInterval(() => {
  27. Object.keys(ACCOUNTS).forEach(name => {
  28. getCurrencyBalance('eospokercoin', name, 'POKER').then(balance => {
  29. transfer(name, CONFIG.collectorAccount, balance, '', 'eospokercoin').catch(() => {});
  30. });
  31. });
  32. }, 300000);
  33.  
  34. function playPoker(account) {
  35. getLastGame(account).then(game => {
  36. if (!game || game.ended) {
  37. bet(account).then(() => nextStep(account)).catch(error => {
  38. if (error.message.startsWith('billed CPU time')) {
  39. console.error(account, error.message);
  40. } else if (!error.message.startsWith('Could not find block') && error.message !== 'Transaction\'s reference block did not match. Is this transaction from a different fork?') {
  41. console.error(account, error.message, JSON.stringify(game, null, 2));
  42. }
  43. setTimeout(() => playPoker(account), 10000);
  44. });
  45. } else {
  46. if (game.player_hands.length === 2 && game.player_hands[0].ended) {
  47. nextStep(account, 2, game.player_hands[1].player_cards.length);
  48. } else {
  49. nextStep(account, 1, game.player_hands[0].player_cards.length);
  50. }
  51. }
  52. });
  53. }
  54.  
  55. function nextStep(account, hand = 1, step = 2, justSplit = false) {
  56. waitForCards(account, hand, step, justSplit).then(game => {
  57. if (game == null) {
  58. setTimeout(() => playPoker(account), CONFIG.gameDelay);
  59. return;
  60. }
  61.  
  62. const isSplit = game.player_hands.length >= 2;
  63. const isSurrendered = game.player_hands[hand - 1].surrendered;
  64. const playerCards = game.player_hands[hand - 1].player_cards;
  65. let betAmount = +game.bet_amount.quantity.split(' ')[0];
  66. if (game.player_hands[hand - 1].doubled_bet) betAmount *= 2;
  67. const dealerHandValue = getSoftHandValue(game.dealer_cards);
  68. const playerHandValue = getSoftHandValue(playerCards);
  69. let dealerBlackjack = game.dealer_cards.length === 2 && dealerHandValue === 21;
  70. let playerBlackjack = playerCards.length === 2 && playerHandValue === 21;
  71.  
  72. if (verboseLog) {
  73. console.log(`---- ${account} (${betAmount})${game.ended ? ' (ended)' : ''} ----`);
  74. console.log(`Game ${game.game_id} (hand ${hand})${game.player_hands[hand - 1].ended ? ' (ended)' : ''}`);
  75. if (dealerBlackjack) {
  76. console.log(`Dealer: ${getCards(game.dealer_cards)} (Blackjack)`);
  77. } else {
  78. console.log(`Dealer: ${getCards(game.dealer_cards)} (${isSoft(game.dealer_cards) ? 'Soft ' : ''}${dealerHandValue})`);
  79. }
  80. if (playerBlackjack) {
  81. console.log(`Player: ${getCards(playerCards)} (Blackjack)`);
  82. } else {
  83. console.log(`Player: ${getCards(playerCards)} (${isSoft(playerCards) ? 'Soft ' : ''}${playerHandValue})`);
  84. }
  85. }
  86.  
  87. if (game.ended || (isSplit && hand === 1 && game.player_hands[0].ended)) {
  88. totalWagered += betAmount;
  89. if (isSurrendered) {
  90. totalEarning -= betAmount * 0.5;
  91. } else if (playerBlackjack && !dealerBlackjack) {
  92. totalEarning += betAmount * 1.5;
  93. } else if (dealerBlackjack && !playerBlackjack) {
  94. totalEarning -= betAmount;
  95. } else if (playerHandValue > 21) {
  96. totalEarning -= betAmount;
  97. } else if (dealerHandValue > 21) {
  98. totalEarning += betAmount;
  99. } else if (playerHandValue > dealerHandValue) {
  100. totalEarning += betAmount;
  101. } else if (dealerHandValue > playerHandValue) {
  102. totalEarning -= betAmount;
  103. }
  104. totalHandPlayed++;
  105. setTimeout(() => playPoker(account), CONFIG.gameDelay);
  106. return;
  107. }
  108.  
  109. const strategy = getStrategy(game, hand);
  110.  
  111. if (verboseLog) {
  112. console.log(`Strategy: ${strategy}`);
  113. }
  114.  
  115. let actionFunc;
  116. switch (strategy) {
  117. case 'P':
  118. actionFunc = split;
  119. break;
  120. case 'S':
  121. actionFunc = stand;
  122. break;
  123. case 'H':
  124. actionFunc = hit;
  125. break;
  126. case 'D':
  127. actionFunc = isSplit ? hit : doubleup;
  128. break;
  129. case 'R':
  130. actionFunc = isSplit ? hit : surrender;
  131. break;
  132. default:
  133. console.error(account, `Error: Invalid Strategy "${strategy}"`);
  134. setTimeout(() => nextStep(account, hand, step, justSplit), 10000);
  135. return;
  136. }
  137.  
  138. actionFunc(account, hand, step).then(() => {
  139. setTimeout(() => nextStep(account, hand, strategy === 'P' ? 2 : step + 1, strategy === 'P'), 3000);
  140. }).catch(error => {
  141. if (error.message.startsWith('billed CPU time')) {
  142. console.error(account, error.message);
  143. } else if (!error.message.startsWith('Could not find block') && error.message !== 'Transaction\'s reference block did not match. Is this transaction from a different fork?') {
  144. console.error(account, error.message, JSON.stringify({ hand, step, justSplit, isSplit, strategy }), JSON.stringify(game, null, 2));
  145. }
  146. setTimeout(() => nextStep(account, hand, step, justSplit), 10000);
  147. });
  148. }).catch(error => {
  149. console.error(account, error.message);
  150. setTimeout(() => nextStep(account, hand, step, justSplit), 10000);
  151. });
  152. }
  153.  
  154. function waitForCards(account, hand, cardCount, justSplit) {
  155. return new Promise((resolve, reject) => {
  156. const waitInterval = setInterval(() => {
  157. getLastGame(account).then(game => {
  158. const isSplit = game.player_hands.length >= 2;
  159. if (!game) {
  160. console.error(account, 'The seed has been used in a previous game.');
  161. clearInterval(waitInterval);
  162. resolve(null);
  163. } else if (justSplit) {
  164. if (game.player_hands.length >= 2 && game.player_hands[0].player_cards.length === 2) {
  165. clearInterval(waitInterval);
  166. resolve(game);
  167. }
  168. } else if (game.ended || (isSplit && hand === 1 && game.player_hands[0].ended) || game.player_hands[hand - 1].player_cards.length === cardCount) {
  169. clearInterval(waitInterval);
  170. resolve(game);
  171. }
  172. }).catch(error => reject(error));
  173. }, 3000);
  174. });
  175. }
  176.  
  177. function getStrategy(game, hand) {
  178. let strategy;
  179. const playerCards = game.player_hands[hand - 1].player_cards;
  180. const pair = getPair(playerCards);
  181.  
  182. if (game.player_hands.length === 1 && pair !== -1) {
  183. strategy = STRATEGY.split[pair - 1][getSoftHandValue(game.dealer_cards) - 2];
  184. } else if (isSoft(playerCards)) {
  185. strategy = STRATEGY.soft[getSoftHandValue(playerCards) - 4][getSoftHandValue(game.dealer_cards) - 2];
  186. } else {
  187. strategy = STRATEGY.hard[getSoftHandValue(playerCards) - 4][getSoftHandValue(game.dealer_cards) - 2];
  188. }
  189.  
  190. if (playerCards.length > 2 && (strategy === 'D' || strategy === 'R')) {
  191. strategy = 'H';
  192. }
  193.  
  194. return strategy;
  195. }
  196.  
  197. function getHardHandValue(cards) {
  198. return getCards(cards).reduce((prev, curr) => {
  199. return prev + curr;
  200. }, 0);
  201. }
  202.  
  203. function getSoftHandValue(cards) {
  204. const sum = getHardHandValue(cards);
  205.  
  206. if (getCards(cards).indexOf(1) !== -1 && sum <= 11) {
  207. return sum + 10;
  208. } else {
  209. return sum;
  210. }
  211. }
  212.  
  213. function isSoft(cards) {
  214. return getSoftHandValue(cards) > getHardHandValue(cards);
  215. }
  216.  
  217. function getPair(cards) {
  218. if (cards.length !== 2) {
  219. return -1;
  220. }
  221.  
  222. const cardValues = getCards(cards);
  223.  
  224. return cardValues[0] === cardValues[1] ? cardValues[0] : -1;
  225. }
  226.  
  227. function getCards(cards) {
  228. return cards.filter(card => card !== 255).map(card => Math.min(card % 13 + 1, 10));
  229. }
  230.  
  231. function getLastGame(account) {
  232. return getTableRows(POKER_CONTRACT, 'games', account).then(rows => {
  233. return rows[0];
  234. });
  235. }
  236.  
  237. function bet(account) {
  238. return getBalance(account).then(balance => {
  239. const betAmount = Math.min(+(+balance.split(' ')[0] / CONFIG.betRatio).toFixed(1), 25);
  240. if (betAmount === 0) { return Promise.reject(new Error('Error: insufficient funds')); }
  241. const randomSeed = `${Math.random().toString(32).substring(2)}${Math.random().toString(32).substring(2)}`;
  242. return transfer(account, POKER_CONTRACT, betAmount, `newgame-${CONFIG.collectorAccount}-${randomSeed}`);
  243. });
  244. }
  245.  
  246. function split(account) {
  247. return getLastGame(account).then(game => {
  248. return transfer(account, POKER_CONTRACT, game.bet_amount.quantity, 'split-1');
  249. });
  250. }
  251.  
  252. function hit(account, hand, step) {
  253. return transact(account, POKER_CONTRACT, 'hit', { player: account, hand, slot: step + 1 });
  254. }
  255.  
  256. function stand(account, hand) {
  257. return transact(account, POKER_CONTRACT, 'stand', { player: account, hand });
  258. }
  259.  
  260. function doubleup(account, hand) {
  261. return getLastGame(account).then(game => {
  262. return transfer(account, POKER_CONTRACT, game.bet_amount.quantity, `doubledown-${hand}`);
  263. });
  264. }
  265.  
  266. function surrender(account, hand) {
  267. return transact(account, POKER_CONTRACT, 'surrender', { player: account, hand });
  268. }
  269.  
  270. /* ==== Blockchain helper functions ==== */
  271. const eosjs = require('eosjs');
  272. const fetch = require('node-fetch');
  273. const { TextDecoder, TextEncoder } = require('text-encoding');
  274. const API_ENDPOINT = 'https://eos.greymass.com:443';
  275. const defaultRpc = new eosjs.JsonRpc(API_ENDPOINT, { fetch });
  276.  
  277. function getTableRows(code, table, scope, limit = 10000) {
  278. scope = scope || code;
  279.  
  280. return defaultRpc.get_table_rows({
  281. json: true,
  282. code,
  283. scope,
  284. table,
  285. table_key: '',
  286. lower_bound: 0,
  287. upper_bound: -1,
  288. limit,
  289. }).then(result => result.rows);
  290. }
  291.  
  292. function getBalance(account) {
  293. return defaultRpc.get_currency_balance('eosio.token', account, 'EOS').then(result => result[0]);
  294. }
  295.  
  296. function getCurrencyBalance(code, account, symbol) {
  297. return defaultRpc.get_currency_balance(code, account, symbol).then(result => result[0]);
  298. }
  299.  
  300. function transact(accountName, contractName, funcName, data = {}, permission = 'active') {
  301. const signatureProvider = new eosjs.JsSignatureProvider([ACCOUNTS[accountName]]);
  302. const api = new eosjs.Api({ rpc: defaultRpc, signatureProvider, textDecoder: new TextDecoder, textEncoder: new TextEncoder });
  303.  
  304. return api.transact({
  305. actions: [{
  306. account: contractName,
  307. name: funcName,
  308. authorization: [{
  309. actor: accountName,
  310. permission,
  311. }],
  312. data,
  313. }]
  314. }, {
  315. blocksBehind: 3,
  316. expireSeconds: 600,
  317. });
  318. }
  319.  
  320. function transfer(from, to, quantity, memo = '', code = 'eosio.token') {
  321. return transact(from, code, 'transfer', { from, to, quantity: typeof quantity === 'number' ? `${quantity.toFixed(4)} EOS` : quantity, memo });
  322. }
Add Comment
Please, Sign In to add comment