Wizards and Warrors

Started by
23 comments, last by LorenzoGatti 6 years, 5 months ago
48 minutes ago, TheSpire said:

Hi there,

I am not a really experienced programmer, so tell me if I am wrong, but, can't we use the 'is' key word to simply check if the weapon that we are using is a sword or a staff?

Like this:

image.png.acb7a2729572aac027e6d91931a1b47f.png

That effectively wouldn't do anything, casting is just changing how you interpret the type of a thing, and you're basically casting it to a staff and then setting a weapon reference to it, meaning if you try to access it through weapon you'll get a reference to a weapon back. If you wanted to access the -staff- part of weapon then you would just set the private weapon to the incoming staff, then cast it to a staff later when you need to cast it.

If effect that private Weapon is only ever going to act like a weapon, even if its pointing to a subclass of weapon like a Sword. Keyword Is would be using type identification to figure out it is a sword, which you could do, but has some caveats and I'm not sure about performance. In a language like C++ you'd usually provide some kind of identifier to know how to cast something to a subclass, like an enum you set.

I'm not entirely sure how that would help with the problem presented in the thread so far either. You could technically reject certain weapon types in the set function for weapon like that, but, you'd then need to know the types ahead of time, and you would probably be better served making something like an Equip function that does it instead. In the context of this thread I would suspect you'd get more than a few people saying that Staff and Sword do not necessarily even need to be a subclass of a weapon.

Advertisement
8 minutes ago, Satharis said:

That effectively wouldn't do anything, casting is just changing how you interpret the type of thing thing

I know that, the goal is just to make sure you can cast it to staff, I believe you can't cast Weapon to staff, so trying to use the property with a Weapon object wouldn't set the var value, and with that you knew that when needed you will be casting a staff from the weapon var and not any other weapon. I might be wrong though...

TheSpire

2 minutes ago, TheSpire said:

I know that, the goal is just to make sure you can cast it to staff, I believe you can't cast Weapon to staff, so trying to use the property with a Weapon object wouldn't set the var value, and with that you knew that when needed you will be casting a staff from the weapon var and not any other weapon. I might be wrong though...

Technically in that case you would be correct, it would stop you from passing in anything but a staff, but that's a bit of a weird way to do it, and like I said the caveat is that you have to know that it needs to be a -staff- ahead of time, essentially hardcoding it. The set function is just that though, a function, so you could basically replicate the behavior an "equip" function would have in it. But that might be a bit confusing to a user.

My other point was casting it to staff was kinda superfluous. If it passes the if statement you can just set weapon = value; and it would work the same. The if statement is a gate essentially.

1 minute ago, Satharis said:

My other point was casting it to staff was kinda superfluous. If it passes the if statement you can just set weapon = value; and it would work the same. The if statement is a gate essentially.

Well yeah, that's true...

TheSpire

On 3/6/2018 at 3:53 PM, Satharis said:

In terms of the comparison there isn't really getting around using an enum or something similar. Either the weapon or the thing adding the weapon needs to know if it can be added/equipped, and the only way to do that is to compare it to something known ahead of time and determine if it is true or false. Your options are rather limited in that area, if you don't compare against a weapon type then you'll have to compare against the item i'd or if it implements an interface or something else. These all equate to identifying what the thing is.

@Satharis I think your answer summed it up pretty well.

So my next question is, you have to have some level of trust in the developer who is writing subclasses of Weapon to include a private enum and a method to access the enum and verify it. I guess afterward you would test it to ensure that a Sword does in fact have a WeaponType.Sword declared privately or look at the code :D.

Another option is to work with capabilities, or just plain tags.

For example, you can have tags for "weapon attributes" and you'd say that a Player can only carry a Weapon if the Players Acceptable Weapon Attributes intersected with the Weapons Weapon Attributes is non-empty.


class Weapon {
  public set<WeaponAttribute> weapon_attributes;
};

class Player {
  public set<WeaponAttribute> acceptable_weapon_attributes;
  bool can_add_weapon(Weapon *w) {
    return w->weapon_attributes.intersect(acceptable_weapon_attributes).empty() == false;
  }
};

Another benefit is that a Warrior that gets the Special Blessing of the Dark God now can use weapons of type EvilMagicWeapon, because you added that WeaponAttribute to the set of acceptable weapon attributes. Note that you'd probably have multiple class attributes for each weapon, to capture different special properties of each weapon.

Btw, This flatter hierarchy is also is much more flexible than "Wizard is a Player." Adding capabilities and delegation is usually much better than trying to model things with inheritance, in my experience.

 

enum Bool { True, False, FileNotFound };

If I'm not mistaken, though perhaps not in the older rules, but in the current rules, unless you just don't meet a prerequisite of the weapon, such as a strength prerequisite, anyone can in fact wield anything.  The only impact being if your proficiency bonus is added to your attack rolls.

Furthermore, wouldn't the simplest solution to this dilemma, would that you wanted to restrict equipment, be to in fact just modify your equip function to validate for you?  Make your 'weapon' class, have subclasses for each 'type' of weapon, and inherit the base, overwrite a Type with the given weapon's type, and then have an array in your player type, warrior, wizard, etc; of available equipment, then you can theoretically add to that array, or perhaps vector would be better?  anyway, you can add to that if you attain certain feats or proficiencies that enable you to expand your repertoire. 

I think many of you are missing the fact that he specifically says he wants the error caught at compile time, something I don't agree is necessary, otherwise the problem is trivial.

 

Quote

The whole point of capturing this thing in the type system is that the violation gets discovered at compile time.

 

Engineering Manager at Deloitte Australia

Quote

he wants the error caught at compile time

Then it's probably best to use Haskell.

Although the "tag" approach will work fine as a template metaprogramming constraint.

enum Bool { True, False, FileNotFound };

C# does not know about something like Template Metaprogramming at all and so it will be not possible to test "if a sword has a sword tag added to it" until you run a post-compilation test.

Depending on the kind and dynamicness of the item system if using an interface and forcing a class to be of type IEquipment or IItem at least one of the other ways I could imagine is using an ECS or tagging system. If I needed to design such a system (as it did in the past for some RPG kind Unity project); Weapons would have tags that describe there nature and behavior like in the printed version of <your known PnP here>. A sword is no more than a collection of data that may or may not be fixed, while fixed data is read from an asset(database), dynamic data like additional buffs is added as tag (or component).

A player or NPC is an actor. Each actor has the ability to do actions while actions have an actor and possibly any combination of targets and/or conditions. Equipping an item then is an action that checks its actor (the player) and a target (the weapon) if it is possible to do its work (putting the items reference Id into the players left/right hand inventory slot) and results in success or failure. That action needs to know a little meta information about whatever it is doing its work at, so the equip action knows to check an items tags (weapon type, other requirements), its target slot (left/right hand, is the slot already used) and the actor classes "Class" tag/component and the stats every actor has (strength, dexterity ... if we assume that actors can be characters only) to determine if the requirements are met. On success it does whatever it is doing and on failure sends an error message to the print component.

Buffs and debuffs can now manipulate actions by changing requirements and/or tags/components on players and items.

This topic is closed to new replies.

Advertisement