python how to to make set of rules for each class in a game

  • Last Update :
  • Techknowledgy :

Because we're cool kids, let's start with writing down our rules as text:

rules = [
   "Human is Person",
   "Orc is Person",
   "Person may wield Weapon",
   "Human may not wield Axe",
   "Orc may only wield Axe",
   "Sword is Weapon",
   "Bow is Weapon",
   "Axe is Weapon",
   "Cow is Animal",
   "Animal may eat Grass"
]

We know that our "things" have different types, a name, and a way to invoke an "action", so here's our Thing class:

class Thing:
   def __init__(self, name, * type):
   self.name = name
self.type = ['Thing', * type]

def action(self, action_class, * args):
   action_class(self, * args)()

Now, here's what a generic Action could look like:

class Action:
   def __init__(self, name, a, b):
   self.name = name
self.a = a
self.b = b

def invoke(self):
   print('You feel a strange sensation...')

def forbidden(self):
   print(f "{self.a.name} tries to {self.name} {self.b.name}, but that is not possible")

def __call__(self):
   if Rules.allowed(self):
   self.invoke()
else:
   self.forbidden()
print('----------')

Here's the Rules class:

class Rules:
   alias_list = []
prohibition_list = []
permission_list = []
exclusive_list = []

def parse_rules(rules):
   for rule in rules:
   if ' is ' in rule:
   type, alias = rule.split(' is ')
Rules.alias_list.append((type, alias))
elif ' may only ' in rule:
   obj, rest = rule.split(' may only ')
action, second = rest.split(' ')
Rules.exclusive_list.append((obj, action, second))
elif ' may not ' in rule:
   obj, rest = rule.split(' may not ')
action, second = rest.split(' ')
Rules.prohibition_list.append((obj, action, second))
elif ' may ' in rule:
   obj, rest = rule.split(' may ')
action, second = rest.split(' ')
Rules.permission_list.append((obj, action, second))

def resolve_types_inner(types, aliases):
   for (source_type, alias_type) in aliases[: ]:
      if source_type in types:
   types.add(alias_type)
aliases.remove((source_type, alias_type))
return Rules.resolve_types_inner(types, aliases)
return types

def resolve_types(thing):
   types = set(thing.type)
return Rules.resolve_types_inner(types, Rules.alias_list[: ])

def allowed(action_to_test):
   a_types = Rules.resolve_types(action_to_test.a)
b_types = Rules.resolve_types(action_to_test.b)

for (a, action, b) in Rules.exclusive_list:
   if action == action_to_test.name:
   if a in a_types and b in b_types:
   print('-- allowed by exclusive_list')
return True

for (a, action, b) in Rules.prohibition_list:
   if action == action_to_test.name:
   if a in a_types and b in b_types:
   print('-- forbidden')
return False

for (a, action, b) in Rules.permission_list:
   if action == action_to_test.name:
   if a in a_types and b in b_types:
   if not action in (x
      for (a2, x, b2) in Rules.exclusive_list
      if x == action and a2 in a_types):
   print('-- allowed')
return True
else:
   print('-- forbidden by exclusive_list')
return False
print('-- no rules match')

Let us run the following:

# prepare our simple rule engine
Rules.parse_rules(rules)

# Let some things exist in the world
Carl_the_Human = Thing('Carl', 'Human')
Grump_the_Orc = Thing('Grump', 'Orc')
Sandy_the_Cow = Thing('Sandy', 'Cow')
Carls_sword = Thing("Carl's Sword of Justice", 'Sword')
Grumps_axe = Thing("Grump's rusty Axe", 'Axe')
Old_bow = Thing("An old bow", 'Bow')

# Sandy is hungry
Sandy_the_Cow.action(Wield, Grumps_axe)
Sandy_the_Cow.action(Eat, Grumps_axe)
Sandy_the_Cow.action(Eat, Thing("a bunch of grass", "Grass"))

# Carl wants to
try some weapons
Carl_the_Human.action(Wield, Carls_sword)
Carl_the_Human.action(Wield, Grumps_axe)
Carl_the_Human.action(Wield, Old_bow)

# Grump wants to
try some weapons
Grump_the_Orc.action(Wield, Grumps_axe)
Grump_the_Orc.action(Wield, Carls_sword)

Here is an example implementation:

class Weapon:
   def __init__(self, damage):
   self.damage = damage

class Gun(Weapon):
   def __init__(self):
   Weapon.__init__(self, 300)

class Grenade(Weapon):
   def __init__(self):
   Weapon.__init__(self, 1000)

class Knife(Weapon):
   def __init__(self):
   Weapon.__init__(self, 50)

class Hammer(Weapon):
   def __init__(self):
   Weapon.__init__(self, 100)

class Character:
   def __init__(self, name, default_weapon, additional):
   self.name = name
self.default_weapon = default_weapon
self.additional = additional

def attack(self):
   pass # some implementation

class Heavily_armed(Character):
   def __init__(self, name):
   Character.__init__(self, name, Gun(), Grenade())

class Lightly_armed(Character):
   def __init__(self, name):
   Character.__init__(self, name, Knife(), Hammer())

class Human(Lightly_armed):
   def __init__(self, name, age, height):
   Lightly_armed.__init__(self, name)
self.height = height
self.age = age

class Orc(Heavily_armed):
   def __init__(self, name, danger):
   Heavily_armed.__init__(self, name)
self.danger = danger

Suggestion : 2

To do that, first you’ll implement a good method of keeping track of which keys are being pressed at a given moment. You can do this simply by making an array of key states that holds the state of each key you want to use for the game.,Add the following code to the end of game.py (with one indentation level, putting it at the same level as the for loop):,Add the following code to game.py at the end of section #2 (after you set the screen height and width):,Try all of this code out by running the game. Now you should start seeing some real gameplay – you can shoot, move, turn, and badgers try to run at you.

If you did it correctly, you should see something like this:

Python 2.7 .3(v2 .7 .3: 70274 d53c1dd, Apr 9 2012, 20: 52: 43)[GCC 4.2 .1(Apple Inc.build 5666)(dot 3)] on darwin
Type "help", "copyright", "credits"
or "license"
for more information. >>>

If, on the other hand, it outputs an error like what’s shown below, then PyGame is not installed.

Python 2.7.2 (default, Jun 20 2012, 16:23:33)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygame
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
      ImportError: No module named pygame
      >>>

Run IDLE and open a new text editor window, as mentioned in the previous section. Type the following code into the editor window:

# 1 - Import library
import pygame
from pygame.locals
import *

# 2 - Initialize the game
pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))

# 3 - Load images
player = pygame.image.load("resources/images/dude.png")

# 4 - keep looping through
while 1:
   # 5 - clear the screen before drawing it again
screen.fill(0)
# 6 - draw the screen elements
screen.blit(player, (100, 100))
# 7 - update the screen
pygame.display.flip()
# 8 - loop through the events
for event in pygame.event.get():
   # check
if the event is the X button
if event.type == pygame.QUIT:
   #
if it is quit the game
pygame.quit()
exit(0)

Add the following code to game.py at the beginning of section #6 (before the player is drawn on screen):

    for x in range(width / grass.get_width() + 1):
       for y in range(height / grass.get_height() + 1):
       screen.blit(grass, (x * 100, y * 100))
    screen.blit(castle, (0, 30))
    screen.blit(castle, (0, 135))
    screen.blit(castle, (0, 240))
    screen.blit(castle, (0, 345))

Add the following code to game.py at the end of section #2 (after you set the screen height and width):

keys = [False, False, False, False]
playerpos = [100, 100]

Suggestion : 3

Class definitions can appear anywhere in a program, but they are usually near the beginning (after the import statements). Some programmers and languages prefer to put every class in a module of its own — we won’t do that here. The syntax rules for a class definition are the same as for other compound statements. There is a header which begins with the keyword, class, followed by the name of the class, and ending with a colon. Indentation levels tell us where the class ends.,The x and y parameters here are both optional. If the caller does not supply arguments, they’ll get the default values of 0. Here is our improved class in action:,Hint: You must know how to solve the geometry problem before you think of going anywhere near programming. You cannot program a solution to a problem if you don’t understand what you want the computer to do!,When defining a method, the first parameter refers to the instance being manipulated. As already noted, it is customary to name this parameter self.

1
2
3
4
5
6
7
class Point:
   ""
" Point class represents and manipulates x,y coords. "
""

def __init__(self):
   ""
" Create a new point at the origin "
""
self.x = 0
self.y = 0
1
2
3
4
p = Point() # Instantiate an object of type Point
q = Point() # Make a second point

print(p.x, p.y, q.x, q.y) # Each point object has its own x and y
0 0 0 0
from turtle
import Turtle

tess = Turtle() # Instantiate objects of type Turtle
alex = Turtle()