Planet Zephyros Trading Card Game

Smart contracts, token standards, APIs, and coding - everything technical lives here.
Post Reply
PlanetZephyros
Visitor
Visitor
Posts: 4
Joined: Tue Dec 09, 2025 8:37 pm
Been thanked: 1 time
Contact:

Planet Zephyros Trading Card Game

Post by PlanetZephyros »

🚀 Massive progress on TCG Game Creator & NFT Viewer dApp (Electroneum)! Wallet connected, DB humming, metadata fetched & owned cards validated. Team preview slays: #59 Veyra (Def 17/Vit 95), #355 Aurelia (Att 24/Def 72), #364 Verdant Core (Att 36/Def 67).

This code enabled me to map TokenId from Electroneum block explorer to the metadata json files that don't map 1=1 due to randomMint in the Verdant Kin NFT contract:

Code: Select all

const { ethers } = require("ethers");
const fs = require("fs");

const RPC = "https://rpc.ankr.com/electroneum";
const contractAddress = "0x3fc7665B1F6033FF901405CdDF31C2E04B8A2AB4";
const maxSupply = 474;

const abi = [
  "function tokenURI(uint256 tokenId) view returns (string)"
];

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchWithRetry(contract, id, retries = 3) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      const uri = await contract.tokenURI(id);
      if (uri && typeof uri === "string" && uri.length > 0) {
        return uri;
      }
      throw new Error("Empty URI");
    } catch (err) {
      console.log(`Token ${id}: attempt ${attempt} failed (${err.message}).`);
      if (attempt < retries) {
        await sleep(500);
      }
    }
  }
  return null;
}

async function main() {
  const provider = new ethers.JsonRpcProvider(RPC);
  const contract = new ethers.Contract(contractAddress, abi, provider);

  let rows = ["token_id,token_uri"];

  for (let id = 1; id <= maxSupply; id++) {
    console.log(`Processing token ${id}/${maxSupply}…`);

    const uri = await fetchWithRetry(contract, id);

    if (!uri) {
      rows.push(`${id},ERROR`);
      console.log(`❌ Token ${id} failed after all retries.`);
      continue;
    }

    const fileName = uri.split("/").pop();
    rows.push(`${id},${fileName}`);
    console.log(`✅ Token ${id} → ${fileName}`);
  }

  fs.writeFileSync("mapping.csv", rows.join("\n"));
  console.log("mapping.csv generated with retries.");
}

main();
New snag on game creation: Frontend upgraded createGame (7 params w/ metadata), but deployed contract's old (5 params) "Simulation failed: missing revert data". Quick redeploy fix incoming! – dev life. 🔧

Stake CORE, build teams, battle NFTs! Who's in? COMING SOON 🃏 #TCG #NFT #dApp #ETN #Web3Gaming
PlanetZephyros
Visitor
Visitor
Posts: 4
Joined: Tue Dec 09, 2025 8:37 pm
Been thanked: 1 time
Contact:

Re: Planet Zephyros Trading Card Game

Post by PlanetZephyros »

Tonight's plan for @PlanetZephyros was to review the game mechanics. I need to make sure that the formula for calculating winning battles is robust enough that not 1 card is too overpowered and basically wins any battle it is involved with.

Code: Select all

function getRoundResult(uint256[5] memory traits1, uint256[5] memory traits2) internal pure returns (RoundResult memory) {
    // Compute attack and defense using the new formula
    uint256 atk1 = traits1[0] + (traits1[3] / 2); // attack + 0.5 * agility
    uint256 def1 = traits1[1] + (traits1[2] / 2); // defense + 0.5 * vitality
    uint256 core1 = traits1[4];

    uint256 atk2 = traits2[0] + (traits2[3] / 2);
    uint256 def2 = traits2[1] + (traits2[2] / 2);
    uint256 core2 = traits2[4];

    // Compute damage and modified core
    uint256 damage_to1 = atk2 > def1 ? atk2 - def1 : 0;
    uint256 core1_mod = core1 > damage_to1 ? core1 - damage_to1 : 0;

    uint256 damage_to2 = atk1 > def2 ? atk1 - def2 : 0;
    uint256 core2_mod = core2 > damage_to2 ? core2 - damage_to2 : 0;

    uint8 p1_wins = 0;
    uint8 p2_wins = 0;
    int16 round_diff = 0;

    if (core1_mod > core2_mod) {
        p1_wins = 1;
    } else if (core2_mod > core1_mod) {
        p2_wins = 1;
    }

    round_diff = int16(int256(core1_mod) - int256(core2_mod));

    return RoundResult({
        p1_wins: p1_wins,
        p2_wins: p2_wins,
        round_diff: round_diff
    });
}
This is the right direction—cleaner, fairer, and harder to exploit.
Players get more interesting matchups, and your characters finally have meaningful roles.
Post Reply