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

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145

1 Answers1

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.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • 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 '19 at 00:31
  • Check out mapped structs with index in the linked question. It goes mapping(bytes32 => WarriorStruct) warriorStructs; // id => struct – Rob Hitchens Feb 22 '19 at 00:36
  • Definitely takes a while to find firm footing with Ethereum and Solidity. Good luck on your quest. :-) – Rob Hitchens Feb 22 '19 at 00:37