Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More gas efficient #84

Closed
ClaudeZsb opened this issue Aug 4, 2023 · 3 comments
Closed

More gas efficient #84

ClaudeZsb opened this issue Aug 4, 2023 · 3 comments
Assignees

Comments

@ClaudeZsb
Copy link
Collaborator

ClaudeZsb commented Aug 4, 2023

Where we might be wasting gas

1. Constructing a piece from a hero of tier 1/2

Creature: {
  keySchema: {
    index: "uint32",
  },
  schema: {
    health: "uint32",
    attack: "uint32",
    range: "uint32",
    defense: "uint32",
    speed: "uint32",
    movement: "uint32",
    uri: "string",
  },
},
CreatureConfig: {
  keySchema: {
    index: "uint32",
  },
  schema: {
    healthAmplifier: "uint16[]", // decimal 2   // example: [210,330]
    attackAmplifier: "uint16[]", // decimal 2
    defenseAmplifier: "uint16[]", // decimal 2
  },
},

This is how we do now:

  • Read a hero's basic attribute of tier 0 from Creature table. This costs 1 slot. (despite of Creature.uri)

    Here, 1 slot means the gas required for reading a bytes32 from evm.

  • Read the attribute amplifier from CreatureConfig table.
    • there are three types of amplifier that separately applied to Creature.health, Creature.attack and Creature.defense.
    • amplifiers for tier 1 and tier 2 are stored in a dynamic array of uint16.
    • this costs 3 (slots) = 1 + 1 + 1.

So we spend 4 slots in total for constructing a piece of tier 1/2. And it should be clear that this job is done at the first turn of each round. So since a Creature can be packed tightly and stored in one slot, why not store any hero of tier 1/2 in the same way as hero of tier 0. Then we will save 3 slots for every players in every round.

Obviously this optimization is feasible and quiet worth doing. Further more, we can integrate tier info into index of Creature. One suggestion is: (max_tier=255 and max_creature_num=255)

index tier internal_index
length 8 bits 8 bits

Besides, Creature.uri is not used in any game playing. And heroes with same creature index but different tier share the same uri. So we can create a new table to only store uri.

CreatureUri: {
  keySchema: {
    index: "uint8",
  },
  schema: {
    uri: "string",
  },
},
@ClaudeZsb
Copy link
Collaborator Author

ClaudeZsb commented Aug 4, 2023

(based on optimization of 1) 2. Caching run-time piece attributes

Piece: {
  schema: {
    x: "uint8",
    y: "uint8",
    tier: "uint8",
    health: "uint32",
    attack: "uint32",
    range: "uint8",
    defense: "uint32",
    speed: "uint32",
    movement: "uint8",
    maxHealth: "uint32",
    creatureId: "uint32",
  },
},

There was a time when Piece table stores only changable attributes like Piece.x, Piece.y and Piece.health. All the other unchangable attributes could be read from Creature and amplified by CreatureConfig. The reason we added unchangable attributes in Piece is just the same like what we're thinking about 1. Constructing a piece from a hero of tier 1/2. It wastes gas. If we didn't store them in Piece, not only for the first turn but also for each turn of every round, we waste gas for constructing a piece of tier 1/2. At that time we've already noticed the wasting but just chose a not good resolution. So now we're thinking to make it better.

Based on the optimization of 1. Constructing a piece from a hero of tier 1/2, we don't need those unchangable attributes in Piece table ever. New Piece table would look like:

Piece: {
  schema: {
    x: "uint8",
    y: "uint8",
    health: "uint32",
    creatureId: "uint16",
    effects: "uint192", // Will be added in Effect feature
  },
},

And this optimization is also compatible with our implementation of Effect. We've chosen that regenerating real-time attributes' value in every turn(tick()) rather than caching the generated value in a table between turns. It makes also PieceData no longer than bytes32.

@ClaudeZsb
Copy link
Collaborator Author

ClaudeZsb commented Aug 4, 2023

automatic attack strategy of piece

This is the current strategy used by all pieces:

  • given a rule of calculating action priority, for example, <damage_caused> / <attack> * 100 + <number_of_enemy_killed> * 100
  • loop all enemy pieces
    • if it's in attack range, calculate the priority of attacking it, then continue to the next enemy
    • if not, find a path to where the piece can attack this enemy, and calculate the priority, then continue to the next enemy
  • choose the action with the highest priority and do action.

In every turn, for each piece, it will try to attack every enemy piece, calculate the exact damage value it can caused and find the best action to do. It turns out that heroes with less armor will always be focused by enemy. On the one hand, it's not the same strategy of hero in traditional auto-chess game. It's a little bit too intelligent and might lead to a situation where no player buy Mage whose armor is usually less than Warrior. On the other hand, this stragety will become more gas-consuming when we implement effect feature. Because we must additionally consider the effects applied to the piece in turn and effects applied to all it's enemies. It's too complexe to maintain.

So we're thinking to implement a much simpler strategy, like pieces would only try to attack the frontmost enemy. This will make various hero lineups be meaningful.

@ClaudeZsb ClaudeZsb self-assigned this Aug 11, 2023
@ClaudeZsb ClaudeZsb moved this from Todo to In Progress in Long-term dev Aug 11, 2023
This was referenced Aug 16, 2023
@ClaudeZsb ClaudeZsb linked a pull request Aug 16, 2023 that will close this issue
@noyyyy
Copy link
Member

noyyyy commented Aug 24, 2023

close #134

@noyyyy noyyyy closed this as completed Aug 24, 2023
@github-project-automation github-project-automation bot moved this from In Progress to Done in Long-term dev Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants