GithubHelp home page GithubHelp logo

helheimlabs / autochessia Goto Github PK

View Code? Open in Web Editor NEW
21.0 21.0 14.0 30.68 MB

Fully on-chain auto chess, built with MUD

Home Page: https://dev.autochessia.xyz

License: GNU Affero General Public License v3.0

HTML 0.12% TypeScript 38.53% Solidity 58.53% JavaScript 0.12% CSS 1.98% Circom 0.73%
blockchain-game ethereum evm fully-on-chain game mud

autochessia's People

Contributors

aliezsss4 avatar claudezsb avatar noyyyy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

autochessia's Issues

Missing information.

New UI is good, but it miss some info.

  • current level
  • current experience and experience needed to upgrade.

It has something mismatch

  • Currently piece and max piece
  • max health of high tier hero(preparing status)

The waiting room list is sorted by time

Issue :The current issue is that there are too many inactive rooms in the room list. Players who want to quickly join a game cannot start one swiftly.

Solution: List the creation time and last update time of each room.

image

Fake players in the right side

When I start a game with two players, there is four players in the right side. The other two players are from a game that has already ended.

image

private room

Two propositions

  1. private room is combined with a hash of password; a player need to prove in front-end that he knows the password and then joins in the room with the proof; contract should be able to verify the proof.
  2. player with a valid signature of room creator can join in a private room.

We're going to implement this feature through the first way, which will enrich our experience of zk development.

New feature: race of hero

Prerequisite. This feature requires that More gas efficient is resolved.

racial effect

What we want to have is that when a player has a certain number of heroes of the same race, it will give a specific effect to all his heroes. And this mechanism can give birth to a variety of hero combinations.

race representation

Creature: {
  keySchema: {
    index: "uint16",
  },
  schema: {
    race: "uint32",
    health: "uint32",
    attack: "uint32",
    range: "uint32",
    defense: "uint32",
    speed: "uint32",
    movement: "uint32",
  },
},

race is an uint32 and is composited by 8 numbers of length 4 bits. Each number of length 4 bits represents one race and its position within race is fixed.

race race_1 race_2-7 race_8
length 4 bits 24 bits 4 bits

race_* = 0000 or 0001. 0001 represents this creature belongs to race_*

support PvE [ need more discussion ]

PvE is better to have. Some personal thinking:

  1. Some player does not like PvP.
  2. PvP requires at least two players to be online at the same time.
  3. PvE is more flexible than PvP. Anyone can start to play at any time.
  4. Autochess has rougue-like element(hero refreshing, different opponent). So a rougue-like PvE game is very suitable.
  5. PvE will drive us to create somthing or mechanics for rewarding a winner. And the reward is probably some NFT or coin in-game that would affect globally the player's future PvE journey. In another word, we'll need to design the in-game economic system.

To make it a rougue-like autochess, there would be at least:

  1. A new tablePvELevel where enemy lineup, reward of each level are stored.
  2. A new system PvESystem that serves PvE process control, random map generating, random reward generating etc.

Challenges

  1. Do not have experience of devlopping a rougue-like game. (how are data structure, components and systems designed)
  2. At present, lack of equipment, skills, items and buff may make it boring.

More gas efficient

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",
  },
},

feed back [ test on July 29 ]

  • bad UX. When you buy an hero in altar, the last unsold hero would move to the slot where the bought hero previously was. This is becase we technically implement a pop operation of an array through replacing the popped one by the last one.
    1. One way to resolve it is that on the client side, we internally write down and update the index of each hero in the altar after buying and keep each unsold hero as unmoved to player.
    2. The other way is that we update the hero altar to an array of constant length. @noyyyy
  • bad UX. The same issue of hero inventory as the previous one.
  • bad UX. Sometimes, it takes a long time for loading hero images. @noyyyy
  • front-end bug. When you have more than 1 hero on your board, all replacing operations of an hero on board only apply to the last one you put on board. @aLIEzsss4
  • contract bug. Once there were 3 Juggs of the same tier, but they were not merged. When the 4th Jugg was bought, 2 of 3 Juggs did merged with the bought one. @ClaudeZsb
  • mud indexer bug. A while after starting a game, values of tables were not synced and updated. @noyyyy
  • contract bug. In the case of 3 players, sometimes two players had the same other player as their opponent. @ClaudeZsb

Matchmaking

Looks like a quick play button that will only focus the player population into one room for a period of time. Can be extended to ladder point matchmaking.

In addition, for a better multiplayer online UX, should we add a confirm match button similar to Dota 2 accept button, where not accepting could incur penalties?

Smaller waiting room id

PlayerGlobal: {
  keySchema: {
    addr: "address",
  },
  schema: {
    roomId: "bytes32",
    gameId: "uint32",
    status: "PlayerStatus",
  },
},

First of all, roomId is reusable. Then a field of 2**256 seems to be too large and produces waste of storage. PlayerGlobal can be limited into just one slot if we use uint128 instead. Then any read or write of this table could be more gas efficient.

New feature: effect

purpose

In order to realize more complex battle system that supports skills, buffs and debuffs.

Future features like hero abilities, equipment, racial effects would heavily rely on this.

feed back [ test on Aug 3 ]

@noyyyy

  • contract bug. Sell a non-exist hero in inventory.
  • contract bug. Coin income is too high.
  • contract bug. A new bought hero overwrites the hero in the first slot of inventory. This causes the loss of an hero.

@ClaudeZsb

  • contract bug. Revert during tick.

@aLIEzsss4

  • bad UX. Countdown is too fast.
  • front-end bug. Service of automatic ticking is not stable.

Deterministic key for hero when place to board

Now, we use getUniqueEntity to generate key when place a hero to board. It's unpredictable and not deterministic. So we can not use optimistic rendering.

I suggest use the following pattern to generate hero key

keccak256(abi.encode(userAddress, gameId, orderOfHeroOnboard))

Accordingly, we need to delete data in table Hero when place piece back to inventory.

autobattle runs too frequence to take too much network usage

@aLIEzsss4
The autobattle runs on blocknumber increase, it's can lead to excessive rpc call if the block number increase fastly.

useEffect(() => {
const interval = setInterval(async () => {
const number = await getCurrentBlockNumber();
const startTime = Number(startFrom);
setStartBlockNumber((prev) => prev - 1);
setBlockNumber(number);
// console.log(startTime < number, startBlockNumber, status);
if (
startTime < number &&
startBlockNumber <= 0 &&
(currentBoardStatus == 0 || !currentBoardStatus)
) {
// First tick
console.log("first tick");
await autoBattleFn();
} else if (currentBoardStatus == 0 && startBlockNumber < 0) {
// End tick
console.log("End tick");
setStartBlockNumber(roundIntervalTime);
} else if (currentBoardStatus == 1) {
// Running tick
console.log("Running tick");
await autoBattleFn();
}
}, 1000);
return () => {
clearInterval(interval);
};
}, [
startFrom,
roundInterval,
getCurrentBlockNumber,
currentGameStatus,
startBlockNumber,
currentBoardStatus,
]);

The better way is to run the next autobattle only when the previous one is confirmed on chain. In this way, the front end will have a balanced rpc call requence.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.