1

Gm,

I've got a smart contract for 2D board game purposes. There is a struct Unit

struct Unit 
    {
        UnitType unitType;
        uint16 x;
        uint16 y;
        int8 hp;
        int8 dmg;
        address owner;
        bool isTeamLeft;
    }

and a mapping

mapping(uint16 => mapping(uint16 => Unit)) public tileToUnit;

the idea of the mapping was to assign it when new Unit is created, and the main purpose is to have ability to check, given x and y coordinates, if provided coordinates are occupied by any unit and if they are - gain access directly to this Unit.

Since units are moving constantly during the game and fight with each other, I need to change their parameters every move. The problem appears when 2 units fight with each other. Take a look at how fight function is called

if(!fight(_unit,tileToUnit[i][j])) //defender survived

and the fight function itself

function fight(Unit storage _attacker, Unit storage _defender) private returns (bool) ///returns true if defender died
    {   
        _defender.hp -= _attacker.dmg;
        _attacker.hp -= _defender.dmg;

        if (isUnitAlive(_defender)) //defender Survived
        {
            return false;
        }
        
        else
        {
            liquidateUnit(_defender);
            unmapUnit(_defender);
            return true;
        } 
    }

The problem is that when we try to reach second unit while calling fight function, we're not able to reach the storage reference via mapping, therefore when later we do _defender.hp -= _attacker.dmg;, we're not decrementing the actual unit which is saved in storage.

Is there any possibility to solve this issue?

2
  • it is not very clear what is the problem with Ethereum storage when used in your case. Transactions can't be executed concurrently so any issue with two players using the same coordinate is impossible. Maybe it is a bug in your code?
    – Nulik
    Commented Dec 23, 2022 at 1:48
  • @Nulik the problem is that mapping we use is not directly connected with the units that are assigned to storage, and when we call the fight function passing a mapping as a second argument, in fact we're not passing a Unit storage, but a mapping copy of unit. When changing the copy we're not affecting the storage state of unit, but just it's mapping copy.
    – Ghinter
    Commented Dec 23, 2022 at 13:13

1 Answer 1

0

Probably the problem is with your loop, which you don't show.

I guess try changing [i][j] to [j][i]

2
  • I'm afraid it does not solve the issue. The order of [i][j] parameters is correct, but we still can not access storage via mapping and edit specific Unit values.
    – Ghinter
    Commented Dec 22, 2022 at 16:38
  • Point is, you can always use mappings, nested or not, struct or not, that can't be the problem. You're just accessing the wrong indexes, but I have no idea why, because I don't know your other code
    – dk1a
    Commented Dec 22, 2022 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.