"Sword" instances may have specific properties that make them incompatible with a "weapon" superclass. Is a broken sword still a weapon? How about a sword with no handle? Or a sword that has been magically transformed into a flower? Is that still a sword and a weapon, or is it now "really" a flower, and should inherit all flower methods while throwing away all weapon methods?
You can duck type and/or RTTI your way out of this problem, but you can't avoid the fact that traditional OOP is very bad at handling these "it depends" cases, because the only relationship it supports is a strict and static inheritance hierarchy.
Unfortunately many domains, including natural language, can only be described by mutable context-dependent relationships.
In the real world, swords don't turn into flowers, so you might think you're safe. (Except that you might want to include object mutability in a game...)
But in NL the meaning of a phrase can change according to social setting, unstated subtext, speaker gender, age, and even time of day. It's all context, and it can't be ignored without losing essential detail.
All current typing systems seem to be attempts to enforce limited-scope static relationships between opaque atomic objects with more or less static properties.
Mutable context-dependent relationships are everyone's worst nightmare in CS. Academic CS seems to have spent most of its career trying to pretend they don't exist, or if they do, to make them go away.
This is sold on the basis of making more reliable code. In fact it simply doesn't work elegantly for entire classes of problems, including many problems for which it seems to work just fine if you describe them in words, until you have to think about all the possible details.
The worst case output is intolerant brittle code with limited features, and the best is an encrustation of exceptions, edge cases, and work-arounds.
Note I'm not saying there's a simple answer, because there isn't. This is a research-grade problem, and it's barely been considered.
I am saying - beware of simple principles like LSP that claim to solve this problem. Because there are many situations in which they simply don't.
In contrast, non class based languages such as Haskell struggle to model problems that are trivial in OOP, such as how to reuse 90% of existing functionality but override 10% with more specialized behavior. Good luck solving that problem elegantly with type classes.
That always seems to the problem with deep hierarchies after a while. Suddenly you have something where one of the inherited methods shouldn't be there. You can't take it away so you have to do something clunky like throwing an exception or making it empty.
And in defense of inheritance, the Liskov Substitution Principle is extremely useful and makes a lot of sense.
If a function accepts a `Weapon` as parameter, surely you should be able to pass it a `Sword`.