Wow this is amazing!
Closed this issue · 3 comments
This is what I was looking for! I do need some help with using it though. Is there a method to simulate just one attack? For example, a Gorgon uses its 'gore' attack against an elephant on one turn. Which method can I use for that?
Also, do you support spells? Like if a Night Hag uses an 'enfeebling ray' against a commoner, which method would I use for that?
Great work BTW!
Thanks!
Okay. To answer your questions, let's declare the creatures.
donald=DnD.Creature("Donald",base="elephant",alignment='Murica')
xi=DnD.Creature("Jinping",base="gorgon", alignment='**')
theresa=DnD.Creature("Theresa",base="night hag", alignment='Engaland')
"Just one attack" by that do you mean change to secondary attack (I don't have my MM on me)?
The simulations runs n encounters via Encounter(<...>).go_to_war(n)_
, which runs .battle()
n times. The latter method iterates across the creatures running their Creature().act()
method, which makes them decide whether to heal, dodge, attack, free themselves, buff, throw net etc. The attack is called .multiattack()
If you want to override the behaviour of say Donald the elephant to attack regardlessly and at random you can change the class's method act()
import random
from DnD import Encounter
def faux(self,*args,**kawrgs):
print(self)
pass
def trumpconomy(self,verbose=0, assess=0): # a partial copypaste of multiattack... see TrumpMods
if not self.arena.find('alive enemy') and len(self.arena.find('alive ally')) == 1: #TrumpMod: Win when all bar one.
raise Encounter.Victory()
for i in range(len(self.attacks)):
try:
opponent = random.choice([other for other in self.arena.combattants if other is not self]) #TrumpMod kill all bar self.
except IndexError:
raise self.arena.Victory()
if verbose:
verbose.append(self.name + ' attacks ' + opponent.name + ' with ' + str(self.attacks[i]['name']))
# This was the hit method. put here for now.
self.attacks[i]['attack'].advantage = self.check_advantage(opponent)
if self.attacks[i]['attack'].roll(verbose) >= opponent.ac:
# self.attacks[i]['damage'].crit = self.attacks[i]['attack'].crit #Pass the crit if present.
h = self.attacks[i]['damage'].roll(verbose)
opponent.take_damage(h, verbose)
self.tally['damage'] += h
self.tally['hits'] += 1
else:
self.tally['misses'] += 1
import types
# adding the unbound method as a bound method...
donald.act=types.MethodType(trumpconomy, donald)
#lets add an "ally"
rex=DnD.Creature("Rex",base="owlbear",alignment='Murica')
print(DnD.Encounter(donald,rex,xi).battle(verbose=1).masterlog)
In round one Donald attacks his ally Rex! Thus proving the behavior is altered!
Similarly spells. There is a possibility of using the a backdoor override of conc_fx with argument 'custom' during initialisation but that is less flexible.
I have patched a lot of your code, updated some rules and added some monsters. I also added an option to change the number of rounds that monsters battle. In fact, you don’t need to change multiattack() to do the above.
Since your code is difficult to read, all I need to know is if you have implemented condition damage? For instance if a poisonous snake bites an enemy there should be ongoing poison damage. What is the method? If you haven’t I’d be happy to implement it.
Great, I'll have a look at your branch when I get the chance. Thanks.
Yes, true that multiattack()
is the main attack, but I spoke of change to act()
was because it controls the behaviour (e.g. dodging if weakest etc), which is most likely what one would like altered.
I do not believe I ever did that case. Advantage and disadvantage are implemented though.