Translations of this page:

011 class & gauss

step011

class

In the last example, you noticed that some functions need quite a lot of arguments, making them hard to remember and hard to code correctly. While there exist ways to pass whole list of arguments as once, there is another problem becoming visible as soon as you try to model more than 2 combatants:

Each combatant has his own bunch of variables -at the moment only attack, defense and hitpoings, but soon far more- and sooner or later the naming of all those variables will become nasty. Imaging 10 different goblins, each having 5 variables, that make 50 variable names … There must be something like a namespace for variables where you could use the dot.notation like in modules if you refer to random.randint() meaning randint() function of the random module: Stinky.attack to refer to the attack stat value of Stinky.

Such a thing exist, it is called a class.

If you never heard of classes (or object orientatoin) let's imagine you have an … mystical, magical …. goblin making machine1). This machine is wired so that it can create an individual new goblin2). Each time you start the machine, a new goblin is created. So you can create an army of goblins really fast.

Translated into computer language, the goblin creating machine is called a class. Each individual goblin produced by this machine is called an instance of this class. Each goblins has his own (personal, local) variables like attack and hitpoints. Those are called attributes (of the class instance). Each goblin can also have his own defined functions, like berzerk() or flee(), those are called methods ( of the class instance). There exist also attributes (and even methods) shared by all goblins together, those are called class attributes or class methods but are not so important right now.

The nice things about using a class for goblins are:

  • Each goblin can have his own, personal values for attributes, with the dot notation. To refer to Stinky's attack value, i code stinky.attack or grunty.hitpoints.
  • If i change stinkys hitpoints, this does not change the hitpoints of other goblins…each attribute belongs to one instance only.
  • I can even randomize the stat values for each goblin (=each class instance) by using the random module in the class constructor. The constructor is a method with a special name that is automatic executed by python each time a new class instance is created (a new goblin is “born”)
  • With a simple for loop i can create 1000 individual, randomized goblins really fast.
  • classes can inherent methods and attributes from other classes. That means i can first code a generic class Monster() with all generic attributes and methods and later i can create a class Goblin(Monster) Goblin child class inherating everything from the Monster class but adding some extra goblin-specific methods.

online documentatoin

I found the python online documenation about classes helpful for people who already know what a class is. If you never heard of classes before, i recommend working through one of the many excellent python beginner tutorials out there, like Swaroop C. H.'s excellent free A byte of python book.

class demo

source code

click reload on your browser if you see no source code here or visit Github.com

output

Stinky.attack: 5
Grunty.defense: 7
Grunty.hitpoints: 10
Grunty take 4 damage: 6
Grunty says: i am fine
Grunty take 7 damage: -1
Grunty says: i am in bad shape

online

Just click on the graphic…
click me

code discussion

Did you noticed that… ?

  • the name of a class begins with an upper char
  • there is a class attribute, counter that belongs to the class, not to an instance of the class. In this example, the counter is not used, he just exist.
  • the special automatic executed method of a new class instance in python has the special name __init__().
  • Each method of a class requires the argument self. It is a reference to the class instance itself.
step011

better random

Now it is time to rework the Goblin Dice Duel using classes. And while i'm at it, this is a good time to randomize the goblin stat values even better. In the long run, i want this program to simulate epic battles between large armies of goblins… and i will not figure out the stats of each individual goblin myself. That's a job for a computer.

gauss

Let assume that the standard, fresh-from-the-breeding-machine-hatched goblin has on average 20 hitpoints. That means that if you grab 100 random goblins, most will have around 19, 20, or 21 hitpoints, some few elite stubborn goblins will have up to 25 hitpoints while some weaklings will have less than 17 hitpoints. Once-in a million you will find an Übergoblin with 30 hitpoints or an really unworthy creature with around 10 hitpoints.

That is, if the hitpints of goblins are normal (or gauss) distributed.

There are mathematical models to describe such an distribution and even better, the random module of python offers you a function to generate random values following the laws of normal distribution far better than the random.randint() funciton:

The amazing random.gauss() function. Let's take a look at the helpful python online documentation:

random.gauss(mu, sigma)
Gaussian distribution. mu is the mean, and sigma is the standard deviation. 
This is slightly faster than the normalvariate() function defined below.

Wow, that is easy. Just two arguments. Let us experiment a bit, using python shell:

>>> import random
>>> random.gauss(20,2)
21.229611198141817
>>> for x in range(10):
	print(random.gauss(20,2))
 
 
18.731026489131313
20.061439768499362
21.576400870087564
20.467927825773376
19.312368653268773
18.24111326477667
21.357458229193927
20.376858376001735
19.461000722570816
18.468106521404675
>>> for x in range(10):
	print(random.gauss(20,5))
 
 
28.446476929526845
23.715576563098807
26.584354809603987
24.661615398593913
22.951632681091176
14.820343223874811
21.071907880803966
15.610981856583557
7.884089170984463
30.044638262665586
>>> 

As you can see, while all values above center around a mu (or µ or mean) of 20 (hitpoints?), it is a huge difference (even in a small sample of only 10 numbers) if the sigma (or Variance) is 2 or 5. With sigma 5, we got an Übergoblin ( 28 hitpoints! ) as well as pure cannon fodder (only 7 hitpoints) while with sigma 2, all hitpoints were relative close to 20.

Please note that even if you select a very small sigma, it is not impossible that you get an extreme low or high value. It is just very rare. With an big sigma however, you will see values extreme distanced from the mu far more often.

If you interested in the exact mathematic model of normal distribution, Wikipedia has some nice graphics, like this one:

Also the website Wolfram Alpha let you play around with mu and sigma in the webbrowser and generate dynamic charts for you.

step011
1) possible some kind of breeding apparatus
2) out of thin air, or dirt, or whatever

en/python/goblins/step011.txt · Last modified: 2014/01/09 11:07 (external edit)