Skip to content

Instantly share code, notes, and snippets.

@Dexaran
Last active October 6, 2019 12:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Dexaran/db82e6bd4dda05619b4c7f5f478ca5aa to your computer and use it in GitHub Desktop.
Save Dexaran/db82e6bd4dda05619b4c7f5f478ca5aa to your computer and use it in GitHub Desktop.

GalaxEOS smart-contract game

Intro

The game is intended to be developed on top of EOSIO blockchain. The core components of the game will be written in C++ (smart-contracts) and the UI will represent a JS website that will display the state of the game which is obtained from smart-contracts.

Game mechanics

The game represents an open world strategy. Action takes place in space. Players control planets, gather resources, build fleets and fight with each other.

All actions take place and are processed in the EOS blockchain. All game state is fully recorded and stored on the blockchain.

A player should interact with the smart contract during the game. So, the player needs to have a signed up EOSIO account.

The game process requires that information (game state) be read from the smart-contract, as well as that user actions are converted into transactions and broadcasted to EOS network, thus sent to the smart-contract.

All the actions that a player can perform are invocations of various functions of the smart-contract which are performed by signing and sending transactions. This includes:

  • Spawning the player in the game

  • Placing "tasks" in planetary task queue (tasks are resolved automatically then)

  • Giving "orders" to the planetary fleet (these are resolved automaticaly as well)

Every type of actions in the game requires (1) a certain task to be placed and (2) a certain amount of time to complete.

So, what a player can do in the game is limited to

  • placing tasks
  • waiting for the completion time and observing the results

Resources

There are three resource types in the game: metal, crystals, gas.

Metal and crystals are used for building ships and structures. Gas is used as a fuel for fleets.

Map

The game map is an arbitrary size 2D grid. Each cell represents a sector. Each sector may contain a planet or not. Each planet may be colonized by players.

Planets

Planet represents the main game object. A planet may be controlled by a player or it may be empty (awaiting for colonization). The more planets a player has, the more time it will take for him to colonize one more.

Planet has the following characteristics:

  • Size (determines how much structures a planet can support): 20 to 50

  • Temperature (determines resource mining coefficients): 0 to 200

  • Resource storage capacity for each resource: defaults to 1500

The planet serves as the main source of resources in the game. To extract and store resources, the player must build structures on the planet. Fleets of players are also being built on planets.

A fleet may be deployed on the planet.

Building structures

Each structure has building cost, building time and level stats.

  • Metal/ Crystal/ Gas mine: produces X * level metal/ crystal/ gas per second

  • Metal/ Crystal/ Gas storage: Increases metal/ crystal/ gas storage capacity of a planet by X * level units

  • Shield: increases durability of the defensive ships by X * level %

  • Command center: allows to send fleets outside of this planet, has no level mechanic

  • Assembly: allows to build fleets, has no level mechanic

Each building consumes 1 point of Planetary size per level. Once the planetary limit is reached, building costs are doubled for each point of limit exceed. It is possible to "upgrade" a structure by paying its building cost thus increasing its level. Upgrade requires building time to complete.

Ships

There are 3 ship types in a game currently (first release beta):

Battleship

  • Stats: 100 attack/ 150 durability/ 20 cargo

Cargo ship

  • Stats: 10 attack/ 400 durability/ 500 cargo

Colonizer

  • Stats: 10 attack/ 700 durability/ 500 cargo

  • Can colonize a new planet. Will be destroyed upon colonization.

Fleets

When ships are built on a planet, they are automatically added to the fleet of this planet. A player can send some ships outside of a planet if the planet has a "Command center" building. A player chooses how much ships to send and pays the gas cost for the flight - then the ships leave the planet and proceed to their tasks. The amount of time needed for a fleet to reach the destination is determined by the distance between the home planet cell of the fleet and the destination cell.

There are the following task types for the fleets:

  • Attack (attacks an enemy planet)

  • Transport (moves resources to the destination allied planet then returns the fleet back to the home planet)

  • Move (moves the fleet to the destination allied planet and adds it to the destination planet's fleet)

  • Colonize (only for colonizer ships; colonized a planet for the sender player, destroys the colonizer ship)

A player can send resources alongside the fleet to transport. The max amount of resources for transportation is determined by the cargo capacity of the fleet.

Combat

A player can attack another player by sending a fleet with "Attack" order. Damage stats of each fleet (defenders and attackers) are calculated and the damage is simultaneously applied to both fleets. Battleships take damage first. If the amount of damage exceeds the amount of ships durability then the rest of damage is applied to Cargo ships and then to the Colonizers.

If the attackers destroy defending fleets completely then they proceed to gathering resources from planet's storages and return back to their home planet.

Start

Each player starts with 1 planet. There are Metal mine(lvl 1), Crystal mine(lvl 1) structures built at the starting planet.

@Sparke2
Copy link

Sparke2 commented Sep 5, 2019

UI requirements

The UI of the Universe-X game is intended to do two things:

  • obtain data from smart-contract and represent it in a user-friendly form

  • generate contract invocations whenever a user wants to submit an action

Transaction submission and interaction with the blockchain is on Dexaran's side.

Getting data from a smart contract is limited only to reading the “sector” table and parsing it as JSON. In fact it is almost limited to this function call.

UI must run from github pages or downloaded folder with index.html

UI must be written in JS and it must represent an application that could be ran in browser through github pages. So, it must not rely on any external dependencies that could not be committed to the same repo just next to the index.html file.

There should be three layouts

The game UI should be divided into three layouts:

  • Sectors list

  • 2D grid

  • Planet mode

The purpose of Sectors List is to represent sectors in text form and allow player to search among them. Each planet must be represented as an item of the list. When a player clicks on a planet from the list, the interface should switch to the planet display mode.

The purpose of 2D grid is to represent sectors and planets in a more visual geometric form and make it easier for a player to understand the distance between objects at the map and the physical allocation of sectors. Note that the map is generated dynamically and it may contain empty spaces (these are non-existing coordinates, not to be confused with empty sectors which exist and has IDs). The map is filled upon discovery, so when a player sends a fleet to the previously non-existing coordinates the corresponding map cell is generated and appended to the existing map.

Planet mode is intended to represent detailed planet info and allow to make decisions on placing tasks and commanding fleets. A player may enter planet mode to browse any planet, but he(she) can not place tasks for planets that are not owned by this player (the smart-contract will reject transactions and throw an error).

Each planet must have a button "Send a fleet here". When a player clicks the button he(she) must be given a choice where to send fleet from (pick a home planet), how much ships of each type to send, how much cargo to send with a fleet and what is the fleet order type to assign.

Parsing planets

The following planetary variables are important and therefore should be displayed to the player:

  • id of the planet or sector

  • x and y coordinates. These are used to calculate distances between objects.

  • last_updated[0] - timestamp of the last update cycle of the planet. Only the 0 element is important at the moment.

  • has_planet - determines whether the map cell is a planet or an empty sector.

  • temperature determines resource output.

  • size determines max building limit

  • colonization_start and colonization_duration are only important during the colonization period. Zero otherwise.

  • owner_name account of the owner - it is important

  • planetary_buildings array determines which buildings are presented at the planet. Building level must be displayed as well. There are only 9 types of buildings currently. Building two structures of the same type is impossible, so a player can only build one "Metal Mine" per planet and only level up it afterwards. Building above size limit is possible but it will have greatly increased costs.

  • resources - 0 = metal, 1 = crystal, 2 = gas

  • fleets - array of fleets. Each fleet has its order and only exist while the fleet is proceeding to the order. Fleets return home and are merged into the planetary_fleet after the completion of the given order. Fleet can only have one order. Empty fleets are cleared out by the smart-contract automatically. It is important to display the fleets and the remaining time until the completion of their current task. Each fleets array element is the same as planetary_fleet object.

  • fleets.id - system variable, do not display

  • fleets.ships[ 0 or 1 or 2] the number of ships. 0 - the number of battleships in a fleet, 1 - cargoships, 2 - colonizers

  • fleets.cargo[ 0 or 1 or 2] the amount of resources transported by this fleet. 0 - metal, 1 - crystal, 2 - gas

  • fleets.home_id - id of the home planet. Not so important to display because the fleet will be displayed at the "home planet's" planet mode screen.

  • fleets.destination_id - important. ID of the planet that is a target of the fleet currently (this means that the fleet is currently moving towards this planet).

  • fleets.leave_time and fleets.travel_time are required to calculate the remaining time of the fleet task. Note that uint64_t returns the time in seconds, while JS timestamp is calculated in milliseconds.

  • fleets.order - important. Current order of a fleet: 0 - idle, 1 - returning home, 2 - attacking, 3 - transporting cargo then returns home, 4 - moving to the new planet to join its planetary fleet, 5 - colonizing a new planet.

  • building_queue - current building tasks list. Watch building_num for IDs. Quantity is always equal to 0.

  • assembling_queue - current ship construction task list. 0 - battleships, 1 - cargoships, 2 - colonizers. Quantity determines the amount of ships being built.

  • planetary_fleet object represents ships that are currently staying at the planetary orbit. Only ships array matters for planetary_flees because other variables do not represent any useful info since the planetary_fleet will always stay at the orbit of its planet. If the fleet will receive a command to do something then it will turn into a fleet object and it will be extracted into the fleets array (see above).

Planet object example:

{
      "id": 0,
      "x": 0,
      "y": 0,
      "last_updated": [
        1567714743,
        1567670578,
        1567670578,
        1567714743
      ],
      "has_planet": 1,
      "temperature": 120,
      "size": 20,
      "type": 0,
      "name": "",
      "owner": 0,
      "colonization_start": 0,
      "colonization_duration": 0,
      "owner_name": "",
      "planetary_buildings": [
        {
          "type": 0,
          "level": 0
        },
        {
          "type": 1,
          "level": 0
        },
        {
          "type": 2,
          "level": 0
        },
        {
          "type": 3,
          "level": 0
        },
        {
          "type": 4,
          "level": 0
        },
        {
          "type": 5,
          "level": 0
        },
        {
          "type": 6,
          "level": 0
        },
        {
          "type": 7,
          "level": 0
        },
        {
          "type": 8,
          "level": 0
        }
      ],
      "resources": [
        0,
        0,
        0
      ],
      "fleets": [],
      "planetary_fleet": {
        "id": "0",
        "ships": [
          0,
          0,
          0
        ],
        "cargo": [],
        "home_id": 0,
        "destination_id": 0,
        "leave_time": 0,
        "travel_time": 0,
        "order": 0
      },
      "building_queue": [],
      "assembling_queue": []
    }

Important functions

void spawnplayer(eosio::name acc, uint64_t planet_id);

https://github.com/Sparke2/UniverseX/blob/master/include/universe_x.hpp#L236

This function spawns a player at the planet_id sector. Generates the "default planet" if there is no planet in this sector. Impossible to spawn in the already-owned sector.

void addtask(eosio::name acc, uint64_t id, uint64_t type, uint64_t task_id, uint64_t quantity, bool autoupdate);  

https://github.com/Sparke2/UniverseX/blob/master/include/universe_x.hpp#L228

This functions applies a task for the planet if it is owned by the sender of the transaction. Task type may be "building" (0) or "assembling" (1). Task ID determines what to build or assemble depending on the task type. Quantity is always 0 for building tasks and >0 for assembling. bool autoupdate determines if a player wants to queue a deferred transaction to auto-update the planet after the completion of the task (may be true or false here... it doesn't matter now). This will consume CPU bandwidth of EOS account.

void fleetorder(eosio::name acc, uint64_t planet_id, uint64_t destination_id, uint64_t order_type, uint64_t battleship_count, uint64_t cargoship_count, uint64_t colonizer_count, uint64_t cargo_metal,  uint64_t cargo_crystal,  uint64_t cargo_gas);

https://github.com/Sparke2/UniverseX/blob/master/include/universe_x.hpp#L225

This function creates a fleet from by withdrawing ships from planetary_fleet and places the given order for the newly created fleet.

@Sparke2
Copy link

Sparke2 commented Sep 5, 2019

Other functions are system/admin. None of them are important for the UI at the moment.

@Dexaran
Copy link
Author

Dexaran commented Sep 6, 2019

TODO list for the first release:

  • Deploy the implementation of planet.temperature and planet.size mechanics

  • Player access restriction and require_auth

  • Balancing and formulas

  • watchdog function for cyclic updates

@Dexaran
Copy link
Author

Dexaran commented Sep 6, 2019

A list of ideas for the Second Release is withdrawn.
I will share a new gist with involved parties later.

@Dexaran
Copy link
Author

Dexaran commented Sep 6, 2019

@Sparke2

It will take you up to 200x more CPU to maintain this update rates, so it will cost you ~$1200 at the current price rate (which is very likely to change). I'm OK if you decide to pay for it but it may be worth to sacrifice some EOS for RAM and optimize the performance for future use.

Compiled it with -Ofast for testing reasons and it gave 2x performance improvement.

As for CPU and RAM payments - CPU price remains the same. It means that I can invest 1000 EOS in CPU and it will be the same 1000 EOS when I will unstake.

RAM tends to cheapen because the whole EOS ecosystem is trying to make smart-contracts cheaper. Thats why I prefer to sacrifice performance.

@Dexaran
Copy link
Author

Dexaran commented Sep 6, 2019

@Sparke2 unfortunately universe.x name is already registered. Any new name suggestions?

@Sparke2
Copy link

Sparke2 commented Sep 6, 2019

galaxeos.x ? what do you think?

@Sparke2
Copy link

Sparke2 commented Sep 6, 2019

btw top planets were updated half an hour ago. its too long. even for an empty galaxy. lets increase update rate a bit. Your CPU replenishes as i can see.

@Sparke2
Copy link

Sparke2 commented Sep 6, 2019

your 0.0002 EOS will be unstaked in 44 min -_-

@Dexaran
Copy link
Author

Dexaran commented Oct 4, 2019

GalaxEOS UI definition

GalaxEOS UI serves to represent data stored in the game smart-contract and provide a user with the ability to interact with it.

UI must include:

  1. MAP: a Text representation of game state and a 2D grid representation

  2. Detailed planet info layer

  3. Action modeals: currently "send fleet" action only

Map representation: text representation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment