Before we dive into OWL, you can even use RDFS for this sort of thing, but without your custom properties:
ex:SomeFaction rdfs:subClassOf ex:SomeRace .
ex:SomePerson a ex:SomeFaction .
I do not like this approach however, since I view classes as something that describes the immutable essence and structure of entities, which at least factions certainly don't. It might also lead to conflicts in OWL, as some profiles do not allow treating a class as an individual, if you want to use it for other things.
Your issue is similar to trying to describe foaf:membershipClass
with OWL, which is hard to do in general (maybe impossible without hacks). Describing it on a per-case basis is possible however:
[
a owl:Restriction ;
owl:onProperty ex:isOfFaction ;
owl:hasValue ex:SomeFaction
] rdfs:subClassOf [
a owl:Restriction ;
owl:onProperty ex:hasRace ;
owl:hasValue ex:SomeRace
]
This is basically an implication stating that any individual with a specific faction has a specific race.
However, I think you can use transitivity to your advantage here:
ex:isOfGroup a owl:TransitiveProperty .
ex:isOfRace rdfs:subPropertyOf ex:isOfGroup .
ex:isOfFaction rdfs:subPropertyOf ex:isOfGroup .
ex:SomeFaction ex:isOfRace ex:SomeRace .
ex:SomePerson ex:isOfFaction ex:SomeFaction .
We can infer that ex:SomePerson ex:isOfGroup ex:SomeRace
.
With OWL 2, it is simplified to property chains:
[
owl:propertyChainAxiom ( ex:isOfFaction ex:isOfRace )
] rdfs:subPropertyOf ex:hasRace .
The second question needs similar sort of reasoning. I will try to use OWL 2 since I doubt it is expressible in OWL 1.
ex:occupiesContinent owl:propertyChainAxiom ( ex:controlsCity ex:onContinent ) .
ex:occupiedByFaction owl:inverseOf ex:occupiesContinent .
ex:sharesContinentWith owl:propertyChainAxiom ( ex:occupiesContinent ex:occupiedByFaction ) .
ex:alignmentOf owl:inverseOf owl:hasAlignment .
ex:hasSameAlignment owl:propertyChainAxiom ( ex:hasAlignment ex:alignmentOf ) .
The issue with this is that we cannot model conjunction and negation of properties. We can use the example above to model enemies of a particular faction however:
[
owl:intersectionOf (
[
a owl:Restriction ;
owl:onProperty ex:sharesContinentWith ;
owl:hasValue ex:SomeFaction
] [
owl:complementOf [
a owl:Restriction ;
owl:onProperty ex:hasSameAlignment ;
owl:hasValue ex:SomeFaction
]
]
)
] owl:equivalentClass [
a owl:Restriction ;
owl:onProperty ex:isInConflict ;
owl:hasValue ex:SomeFaction
] .
This says that any faction that shares the same continent with one specific faction and does not have the same alignment must be related to the faction is ex:isInConflict
.
I am not sure if there is a better way, but I will update this answer if I find one.