Skip to content

Instantly share code, notes, and snippets.

@RossPfeiffer
Created October 17, 2022 04:42
Show Gist options
  • Save RossPfeiffer/8fa970745d4cd9f4a0fda568b87862c4 to your computer and use it in GitHub Desktop.
Save RossPfeiffer/8fa970745d4cd9f4a0fda568b87862c4 to your computer and use it in GitHub Desktop.
Not done
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract fomoChess{
address x0 = address(0);
address THIS = address(this);
ERC20 x$h33p = ERC20(0x2f712f2c2e4EEE913D15CAa8E4709400D61BFBAc);
address public key;
uint public boards=1;
mapping(uint=>Board) board_by_ID;
mapping(int=>mapping(int=>uint)) public MAP;
mapping(uint=>mapping(int=>uint)) BOARD;//board->index->pieceID
//mapping(int=>mapping(int=>bool)) BOARD;//for starting a board only
struct Board{
uint pieces;
uint jackpot;
uint parent;
}
uint public pieces;
mapping(uint=>Piece) piece_by_ID;
struct Piece{
address owner;
uint kind;//0empty 1pawn 2knight 3bishop 4rooke 5queen 6king . . . 8 gems
uint[] hand;
uint damage;
uint life;
uint lastMove;
uint lastAttack;
uint lastDraw;
mapping(uint/*ID of mechanic*/=>uint/*value applied for mechanic*/) effect;
mapping(uint=>mapping(uint=>uint)) replacedCardsOfDeck;
uint deck;
uint cardsDrawn;
}
mapping(address=>uint) public $$$;
mapping(uint=>uint) public N;
uint genesis;
constructor(){
key = msg.sender;
genesis = block.timestamp;
Board storage board = board_by_ID[1];
board.parent=1;
board_by_ID[1] = board;
MAP[0][0] = 1;
}
event Withdraw( address indexed user, uint amount );
function withdraw() external{
address sender = msg.sender;
uint $_$ = $$$[sender];
$$$[sender] = 0;
x$h33p.transfer(sender,$_$);
emit Withdraw(sender,$_$);
}
bool numbersLocked;
function lockNumbers() external {
require(msg.sender == key);
numbersLocked = true;
}
function rule(uint[] memory indexes, uint[] memory values) external {
require(msg.sender == key && !numbersLocked);
uint L = indexes.length;
for(uint i = 0; i<L; i+=1){
N[indexes[i]] = values[i];
}
}
/*
ace of spades
hearts
diamonds
clubs
*/
mapping(uint=>uint) public boosterPrice;
function boosterPriceUP(uint x) public pure returns(uint){
return x+x/4;
}
event NewBoard(uint boardID, uint parentID, int x, int y);
function spawn(bool developingBoard0_freshBoard1, int boardX, int boardY, uint direction , int x, int y, int x2, int y2, uint[] memory boosterPack) external{
address sender=msg.sender;
uint boosterCosts;
uint L = boosterPack.length;
uint cardcode;
for(uint i;i<L && i<5;i++){
cardcode = boosterPack[i];
require(cardcode<=52);
if(cardcode!=0){
if(boosterPrice[cardcode]==0){
boosterCosts += 1e16;
boosterPrice[cardcode] = boosterPriceUP(1e16);
}else{
boosterCosts +=boosterPrice[cardcode];
boosterPrice[cardcode] = boosterPriceUP(boosterPrice[cardcode]);
}
}
}
require(x$h33p.transferFrom(sender,THIS,boosterCosts+1e17/*cost of pawn*/) && !(x2==x&&y2==y) && L<=5 && x<8 && y<8 && x2<8 && y2<8);
$$$[key] += boosterCosts;
uint board = MAP[boardX][boardY];
if(developingBoard0_freshBoard1){
(int xx,int yy) = cardinal(boardX,boardY,direction);
//boards have to be filled before they can have neighbors
require(board_by_ID[board].pieces == 64);
require(MAP[xx][yy]==0)
boards += 1;
Board storage adjBoard = board_by_ID[boards];
adjBoard.parent = board;
MAP[xx][yy] = boards;
spawnPiece(sender,boards,x,y,x2,y2,boosterPack);
emit NewBoard(boards,board,xx,yy);
}else{
require(board<=boards && board>0 && 0==BOARD[board][y*8+x] && 0==BOARD[board][y*8+x]);
spawnPiece(sender,board,x,y,x2,y2,boosterPack);
}
}
function cardinal(int x,int y, uint direction) internal pure returns(int xx,int yy){
if(direction==0){
xx=x + 1;
}else if(direction==1){
yy=y + 1;
}else if(direction==2){
xx=x - 1;
}else{
yy=y - 1;
}
}
event SpawnPiece(uint board, uint piece, int x, int y, int x2, int y2, uint[] boosterPack);
function spawnPiece(address owner,uint board,int x, int y,int x2, int y2, uint[] memory boosterPack) internal{
pieces+=1;
Piece storage piece = piece_by_ID[pieces];
piece.owner=owner;
piece.lastDraw=rolls;
piece.kind=1;
Board storage _board = board_by_ID[board];
BOARD[board][y*8+x]=pieces;
uint L = boosterPack.length;
for(uint i;i<L;i++){
piece.hand[i] = boosterPack[i];
}
pieces+=1;
piece = piece_by_ID[pieces];
BOARD[board][y2*8+x2]=pieces;
_board.pieces += 2;
emit SpawnPiece(board,pieces,x,y,x2,y2,boosterPack);
}
function proximity(int x1, int x2,int y1, int y2, bool ring)internal pure returns(bool near,int dx,int dy){
int dX = (x1<x2?(x2-x1):(x1-x2));
int dY = (y1<y2?(y2-y1):(y1-y2));
int distX = int(dX);
int distY = int(dY);
if(ring){
return ( (distX+distY == 2 && x1 != x2 && y1 != y2) || (distX+distY == 1), distX, distY);
}else{//if Adjacent
return (distX+distY == 1, distX, distY);
}
}
event Move(uint indexed piece, uint indexed board, int x, int y);
function move(uint board, int piece_loc, int dx, int dy, int[] memory knightPath) external{
address sender = msg.sender;
uint pid = BOARD[board][piece_loc];
Piece storage piece = piece_by_ID[ pid ];
//uint kind = piece.kind;
int[] memory INTS = new int[](5);
INTS[0]=piece_loc%8;
INTS[1]=piece_loc/8;
//i
bool near;
(near, INTS[3], INTS[4]) = proximity(INTS[0],INTS[1],dx,dy,true);
//destination checks
require(
board_by_ID[board].pieces==64 &&
dx<8 &&
dy<8 &&
!(INTS[0]==dx && INTS[1]==dy) &&
piece.damage<piece.life &&
piece.owner == sender &&
block.timestamp-piece.lastMove > 0 &&/*###*/
0<INTS[3]+INTS[4] &&
(
( piece.kind==1 && INTS[3]+INTS[4]==1 )||
( piece.kind==2 && ( (INTS[3]==2 && INTS[4]==1) || (INTS[3]==1 && INTS[4]==2) ) )||
( piece.kind==3 && INTS[3]==INTS[4] )||
( piece.kind==4 && ( INTS[0]==dx || INTS[1]==dy ) )||
( piece.kind==5 && ( INTS[0]==dx || INTS[1]==dy || INTS[3]==INTS[4] ) )||
( piece.kind==6 && near )
)
);
piece_loc = dy*8+dx;
piece.lastMove = block.timestamp;
if(piece.kind == 1 || piece.kind == 3 || piece.kind == 4 || piece.kind == 5 || piece.kind == 6){
if(INTS[3]>0){dx = (dx-INTS[0])/INTS[3];}else{dx=0;}
if(INTS[4]>0){dy = (dy-INTS[1])/INTS[4];}else{dy=0;}
INTS[3] = INTS[3]>INTS[4]?INTS[3]:INTS[4];
}
uint P;
if(piece.kind == 1 || piece.kind == 3 || piece.kind == 4 || piece.kind == 5){
for(INTS[2]=1;INTS[2]<=INTS[3];INTS[2]+=1){
P = BOARD[board][(INTS[1]+dy*INTS[2])*8+(INTS[0]+dx*INTS[2])];
BOARD[board][(INTS[1]+dy*(INTS[2]-1))*8+(INTS[0]+dx*(INTS[2]-1))] = P;
}
}else if(piece.kind == 2){
INTS[3] = knightPath[0]/8;
INTS[4] = knightPath[0]%8;
for(INTS[2]=0;INTS[2]<3;INTS[2]++){
(near,,) = proximity(INTS[0],INTS[1],INTS[3],INTS[4],false);
require(near);
P = BOARD[board][INTS[4]*8+INTS[3]];
BOARD[board][INTS[1]*8+INTS[0]] = P;
INTS[1] = INTS[3];
INTS[0] = INTS[4];
if(INTS[2]!=2){
INTS[3] = knightPath[uint(INTS[2]+1)]/8;
INTS[4] = knightPath[uint(INTS[2]+1)]%8;
}
}
require(INTS[0] == dx && INTS[1] == dy);
}else if(piece.kind == 6){
for(INTS[2]=8;INTS[2]>=1;INTS[2]-=1){
P = BOARD[board][( (INTS[1]+dy*INTS[2])%8 )*8+( (INTS[0]+dx*INTS[2])%8 )];
BOARD[board][( (INTS[1]+dy*(INTS[2]+1))%8 )*8+( (INTS[0]+dx*(INTS[2]+1))%8 )] = P;
}
}
BOARD[board][piece_loc] = pid;
emit Move(pid, board, dx, dy);
}
function isAlive(Piece storage defender)internal view returns(bool){
return defender.damage<defender.life;
}
function claimNaturalResources(uint board) external{
address sender = msg.sender;
Piece storage piece;
bool others;
for(int i;i<64;i++){
piece = piece_by_ID[ BOARD[board][i] ];
if( piece.owner != sender && piece.owner!=x0 && isAlive(piece) ){
others = true;
break;
}
}
if(!others){
Board storage _board = board_by_ID[board];
Board storage parent = board_by_ID[_board.parent];
uint jp = _board.jackpot;
$$$[sender] += jp-jp/10;
parent.jackpot += jp/10;
_board.jackpot = 0;
}
}
event Attack(uint board, int attacker_loc, int defender_loc);
function attack(uint board, int attacker_loc, int defender_loc) external{
address sender = msg.sender;
Piece storage attacker = piece_by_ID[BOARD[board][attacker_loc]];
Piece storage defender = piece_by_ID[BOARD[board][defender_loc]];
(bool adj, int dx, int dy) = proximity(attacker_loc%8,attacker_loc/8,defender_loc%8,defender_loc/8,false);
require(
board_by_ID[board].pieces==64 &&
attacker.owner == sender &&
isAlive(defender) &&
block.timestamp-attacker.lastAttack > 0/*###*/ &&
( adj || (attacker.effect[77/*long reach*/]==1 && dx+dy==2) )
);
attacker.lastAttack = block.timestamp;
damage(defender, 5/*###*/, sender, board);
emit Attack(board,attacker_loc,defender_loc);
}
function damage(Piece storage defender, uint _damage, address accountable, uint board)internal returns(bool kill){
require( isAlive(defender) );
defender.damage+=_damage;
if( !isAlive(defender) ){
board_by_ID[board].jackpot += 1e17/2;
$$$[accountable] += 1e17/2;
return true;
}
return false;
}
uint rolls;
mapping(uint=>uint) seeds;
uint lastRoll;
function secretRandomness(uint seed)external{
require(msg.sender==key);
if( block.timestamp-lastRoll>N[0] ){
seeds[rolls] = seed;
rolls+=1;
lastRoll = block.timestamp;
}else{
revert();
}
}
function draw(uint pieceID)external{
Piece storage piece = piece_by_ID[pieceID];
require(msg.sender == piece.owner);
uint ld = piece.lastDraw;
if(rolls>ld){
uint emptySpots;
uint draws;
uint[] memory handSlots = new uint[](3);
uint i;
for(i;i<5;i++){
if(piece.hand[i]==0){
handSlots[emptySpots] = i;
emptySpots+=1;
}
}
uint pickedCardSlot;
uint card;
uint rpcod;
for(i=0; i<emptySpots && piece.cardsDrawn+i<52; i++){
draws+=1;
pickedCardSlot = uint( keccak256(abi.encodePacked(seeds[ld+1],i,pieceID)) ) % (52-(piece.cardsDrawn+i) );
rpcod = piece.replacedCardsOfDeck[piece.deck][pickedCardSlot];
if(rpcod==0){
card = pickedCardSlot;
}else{
card = rpcod;
}
rpcod = piece.replacedCardsOfDeck[piece.deck][52-piece.cardsDrawn+i];
if(rpcod==0){
piece.replacedCardsOfDeck[piece.deck][pickedCardSlot] = 52-piece.cardsDrawn+i;
}else{
piece.replacedCardsOfDeck[piece.deck][pickedCardSlot] = piece.replacedCardsOfDeck[piece.deck][pickedCardSlot];
}
piece.hand[handSlots[i]] = card;
}
piece.lastDraw = rolls;
piece.cardsDrawn += draws;
}
}
function viewMap(int x, int y, int width, int height) external view returns( uint[] memory IDs, uint[] memory $,uint[] memory pieceCounts, uint[] memory parents ){
IDs = new uint[](uint(width*height));
$ = new uint[](uint(width*height));
pieceCounts = new uint[](uint(width*height));
parents = new uint[](uint(width*height));
int i;
int j;
uint r;
for(i=y;i<height;i++){
for(j=x;j<width;j++){
IDs[r] = MAP[j][i];
$[r] = board_by_ID[ MAP[j][i] ].jackpot;
pieceCounts[r] = board_by_ID[ MAP[j][i] ].pieces;
parents[r] = board_by_ID[ MAP[j][i] ].parent;
r+=1;
}
}
}
function viewBoard(uint board) external view returns( uint[] memory UINTs, address[] memory owners ){
UINTs = new uint[](64*(7+5+10));
owners = new address[](64);
uint i;
uint j;
uint ID;
Piece storage piece;
for(i=0;i<64;i++){
ID = BOARD[board][int(i)];
piece = piece_by_ID[ ID ];
UINTs[i] = ID;
UINTs[i+1] = piece.kind;
UINTs[i+2] = piece.life;
UINTs[i+3] = piece.damage;
UINTs[i+4] = piece.lastMove;
UINTs[i+5] = piece.lastAttack;
UINTs[i+6] = piece.lastDraw;
UINTs[i+7] = piece.cardsDrawn;
UINTs[i+8] = piece.hand[0];
UINTs[i+9] = piece.hand[1];
UINTs[i+10] = piece.hand[2];
UINTs[i+11] = piece.hand[3];
UINTs[i+12] = piece.hand[4];
for(j=0;j<10;j++){
UINTs[i+12+j] = piece.effect[j];
}
}
}
function viewPiece(uint piece) external view
returns(
uint kind,
uint life,
uint _damage,
uint lastMove,
uint lastAttack,
uint lastDraw,
uint cardsDrawn,
uint[] memory hand,
uint[] memory effect
){
uint j;
Piece storage p = piece_by_ID[piece];
kind = p.kind;
life = p.life;
_damage = p.damage;
lastMove = p.lastMove;
lastAttack = p.lastAttack;
lastDraw = p.lastDraw;
cardsDrawn = p.cardsDrawn;
for(j=0;j<5;j++){
hand[j] = p.hand[j];
}
for(j=0;j<10;j++){
effect[j] = p.effect[j];
}
}
}
/*
0 Drawing cards cooldown timer
*/
// ui
// then finally 52 ablities
//whenever a piece dies or moves off board
//if(conquered[boardID][x0]+conquered[boardID][ ... ]==64)
//the cards you hold give you your stats ... attack and speed are the only stats. AJQK for speed, 2-10 for attack
abstract contract ERC20{
function transfer(address _to, uint _value) public virtual returns (bool);
function transferFrom(address src, address dst, uint amount) public virtual returns (bool);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment