1

need a little help if you can spare the time.

Making a little card game where people can collect "warrior" cards.

We'll have an initial 12 master "cards" that supply the initial traits for the warriors. I have a struct "Card" for those and they're in an array "cards".

The idea is that someone who wants to collect a particular card will click on it in our dapp, the id of that card will be passed to a function "addWarrior". That function will first call "getCard" that will retrieve the specifics of that card and then call "createWarrior" to use those details to make a copy of the card. That copy is a Struct called "Warrior" and goes into an array called "warriors".

I'm pretty close to getting it working in Remix. I'm getting an "Invalid implicit conversion" type error when I try to compile the contract.

browser/warriors.sol:61:23: TypeError: Invalid type for argument in function call. Invalid implicit conversion from type(string storage pointer) to string memory requested. createWarrior(string, uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16); ^----^"

Here's my contract code:

pragma solidity ^0.5.0;

contract WarriorFactory {

struct Card {
    string cardName;
    uint16 cardLevel;
    uint16 cardAttack;
    uint16 cardDefend;
    uint16 cardStrategy;
    uint16 cardIssued;
    uint16 maxCards;
}
Card[] public cards;

struct Warrior {
    string warName;
    uint16 level;
    uint16 attack;
    uint16 defend;
    uint16 strategy;
    uint16 winCount;
    uint16 lossCount;
    uint16 warNumber;
    uint16 maxWarriors;
}

Warrior[] public warriors;

function createCard(string memory _cardName, uint16 _cardLevel, uint16 _cardAttack, uint16 _cardDefend, uint16 _cardStrategy, uint16 _cardIssued, uint16 _maxCards) public {
    cards.push(Card(_cardName, _cardLevel, _cardAttack, _cardDefend, _cardStrategy, _cardIssued, _maxCards));
}

function getCard(uint256 id) public view returns (
    string memory _warName,
    uint16 _level,
    uint16 _attack,
    uint16 _defend,
    uint16 _strategy,
    uint16 _warNumber,
    uint16 _maxWarriors) {
        Card storage Crd = cards[id];
        _warName = string(Crd.cardName);
        _level = uint16(Crd.cardLevel);
        _attack = uint16(Crd.cardAttack);
        _defend = uint16(Crd.cardDefend);
        _strategy = uint16(Crd.cardStrategy);
        _warNumber = uint16(Crd.cardIssued);
        _maxWarriors = uint16(Crd.maxCards);

    }

function createWarrior(string memory _warName, uint16 _level, uint16 _attack, uint16 _defend, uint16 _strategy, uint16 _winCount, uint16 _lossCount, uint16 _warNumber, uint16 _maxWarriors) public {
    _winCount = 0;
    _lossCount = 0;
    warriors.push(Warrior(_warName, _level, _attack, _defend, _strategy, _winCount, _lossCount, _warNumber, _maxWarriors));
}

function addWarrior(uint256 id) public {
    getCard(id);
    createWarrior(string, uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16);
}

}

Any ideas on how to clear that up? Or should I be structuring this differently?

I've currently got all the functions set to "public" just to keep initial testing easy, I expect to change those so the "helper functions" will only be called internally before going live.

Thanks a bunch in advance for any advice you can give. Kevin

0

The compiler is upset because the arguments in createWarrior are really types with no values. You can see the errors resolve like this:

function addWarrior(uint256 id) public {
    getCard(id);
    string memory something;
    uint16 something1;
    uint16 something2;
    createWarrior(something, something1, something2, uint16, uint16, uint16, uint16, uint16, uint16);
}

To work with returned values:

function callee(uint arg) public pure returns(bool, uint) {
  return(arg==1, 10);
}

function caller() public pure returns(bool success) {
  bool b;
  uint u;
  (b,u) = callee(1);
}

You're using a very heavy data structure with a lot of data passed around. I'd suggest a leaner approach to this using unique identifiers for both entities.

For example, if mappings are used:

function addCardToWarrior(bytes32 warriorId, bytes32 cardId) public {
  warrior[warriorId].cards.push(cardId);
}

Have a look over here: Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

  • Hi Rob, Thanks for the help. I don't think I can use the mappings approach as once a person collects a "warrior" he'll do things that will cause the attack/defend/strategy values to increase. I think that means I need a struct for each "warrior" collected. I guess I need to figure out how to apply the caller/callee example you showed above. I'm very new to all this so what I don't know how to do is almost immeasurable. – Kevin Phillips Feb 22 at 0:31
  • Check out mapped structs with index in the linked question. It goes mapping(bytes32 => WarriorStruct) warriorStructs; // id => struct – Rob Hitchens - B9lab Feb 22 at 0:36
  • Definitely takes a while to find firm footing with Ethereum and Solidity. Good luck on your quest. :-) – Rob Hitchens - B9lab Feb 22 at 0:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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