Hey guys,
here's the first version of an encounter system. The basic idea is to calculate a percentage, the capability, from the attributes of the character trying to master the encounter. Then the capability is checked five times against a random number between 0 and 99. Then, failures are counted. Very hard encounters allow no failures, very easy ones allow four failures. If the number of failed checks is not greater than the allowed number of failed checks, the encounter has been mastered. For a more detailed explanation, please look at the comments in the code below.
I'm not perfectly happy with the success percentages, but it's good enough I think.
Do you like the system so far?
The goal is that you can later write (for example):
trap = TrapEncounter()
trap.difficulty = 4
trap.characters = [warrior1, warrior2]
success = trap.run_encounter()
@Xela
I will use inheritance to implement this as not using it would multiply lots of code. However, if you insist, we can take the inheritance out when copying the code into RenPy.
The following code is untested, will contain typos and will not run. I show it here so you can review the comments and the basic system.
class BaseEncounter(object):
'''Represents a problem questing characters have to master.
Difficulty
The difficulty describes how hard it is to master this encounter. It ranges
from 'very easy' = 1 to 'very hard' = 5.
Mastering the encounter
In order to master the encounter, the characters must pass a number of
encounter checks equal to the difficulty, e.g. one check for a very easy
encounter or three checks for a normal encounter. If they succeed within
five tries, they master the encounter. If the characters fail at
6 - difficulty encounter checks, e.g. 2 for a hard enounter, they fail the
encounter and collectively suffer consequences.
The encounter check
A random number between 0 and 99 is rolled. If it is lower than the
capability of the character, the check succeeds.
Probability of failure at various capabilities and difficulties
10% capability "Rookie"
'very easy', one successful check needed to master encounter
probability to fail one check: 1 - 0.1 = 0.9
probability to fail all five: 0.9 * 0.9 * 0.9 * 0.9 * 0.9 = 0.59
Rookies succeed at very easy encounters in 41 out of 100 tries.
'very hard', five successful checks needed to master encounter
probability to succeed on one check: 0.1
probability to master all five: 0.1 * 0.1 * 0.1 * 0.1 * 0.1 =0.00001
Rookies succeed at very hard encounters in 1 out of 10000 tries.
90% capability "Master"
'very easy', one successful check needed to master encounter
probability to fail one check: 1 - 0.9 = 0.1
probability to fail all five: 0.1 * 0.1 * 0.1 * 0.1 * 0.1 = 0.00001
Masters succeed at very easy encounters in 9999 out of 10000 tries.
'very hard', five successful checks needed to master encounter
probability to succeed on one check: 0.9
probability to master all five: 0.9 * 0.9 * 0.9 * 0.9 * 0.9 = 0.59
Masters succeed at very hard encounters in 59 out of 100 tries.
'''
def __init__(self):
self.difficulty = 3
self.characters = []
def capability(self, char):
'''Returns how capable the character is at mastering this encounter.
A percentage is returned. 100 means the character will master this
encounter every single time. 1 means the character will master this
encounter in 1 out of 100 tries (on average).
'''
# sub classes must implement this method
return -1
def most_capable(self, charlist):
'''Returns the character most capable of mastering an encounter check.
'''
cap2char = {}
for char in charlist:
# there could be several chars with equal capability
try:
cap2char[self.capability(char)].append(char)
except KeyError:
cap2char[self.capability(char)] = [char]
maxcap = max(cap2char.keys())
most_capable = random.choice(cap2char[maxcap])
return most_capable
def take_check(self, char):
'''A character takes an encounter check, returns True if successful.
'''
roll = random.randint(0, 99)
if roll<self.capability(char):
self.mastered_check(char)
passed = True
else:
self.failed_check(char)
passed = False
return passed
def mastered_check(self, char):
'''Applies the effects of a successful encounter check to the character.
'''
# should increase character tiredness here
char.tiredness += 20
# could also increase happiness, experience, ...
def failed_check(self, char):
'''Applies the effects of a failed encounter check to the character.
'''
# should increase character tiredness here
char.tiredness += 20
# should also apply negative effects: reduce health, happiness
def run_encounter(self):
'''This will play out the encounter.
'''
msg = "no characters defined for encounter '%s'"
assert self.characters, msg % self
# determine the maximum number of failed checks
maxfail = 5 - self.difficulty
# perform up to five encounter checks
failedchecks = 0
for i in range(0, 5):
checkchar = self.most_capable(self.characters)
success = self.take_check(checkchar)
if not success:
failedchecks += 1
# see if the characters mastered the encounter
if failedchecks>maxfail:
mastered = False
for char in self.characters:
self.failed_encounter(char)
else:
mastered = True
for char in self.characters:
self.mastered_encounter(char)
return mastered
def mastered_encounter(self, char):
'''Applies the effects of a mastered encounter to the character.
'''
char.experience += (self.difficulty * self.difficulty)
# could also increase happiness, fame
def failed_encounter(self, char):
'''Applies the effects of a failed encounter to the character.
'''
pass
# should apply negative effects: reduce health, happiness, fame