跳转到内容

Blender 3D:Python 融合/孤儿脚本

来自维基教科书,开放世界中的开放书籍

孤儿脚本

[编辑 | 编辑源代码]

嗨,请将未维护的脚本发布到这里。

注意恶意代码,尤其是 OS 模块,经常检查历史记录以查看编辑以确保没有人做坏事。

目前有两个脚本需要优秀的父母或母亲。

这个脚本是一个简单的 L 系统,允许您使用预定义的网格。它确实在 2.43 中工作,并且可能是一个建筑物生成器(有一些工作要做)。

#
# =====================
# README
# =====================
#
# this is a simple L-system that uses pre-made mesh elemental blocks
#
# source blocks are in a different layer - press tilde (`) in 3d view
# to see them all
#
# a new mesh is created every time; edge creases are carried over from
# source meshes to allow subsurf work
#
# this system uses the turtle concept with pushable/poppable state,
# just like most other L-systems
# however, the "drawing" operation here is to place a pre-made mesh
# instead the usual plant-oriented stuff
# as a result, this should be pretty well suitable for Discombobulator
# style work such as generating lots of small detail
#
# turtle instructions and any other tokens are XML-like tags
# instead of single characters; they can also contain an arbitrary
# argument string
# rewriting rules are actually defined as functions to allow
# procedural flexibility
#
# things left to do really depend on what the actual use is
# some ideas include using lists instead of strings for arbitrary
# argument data (may help with speed); supplying environment
# info to the rule function (for queries, like in some advanced
# L-systems out there) as well as the current model info
# for true Discombobulator-style detail generation there has
# to be a mode to populate the axiom (initial state) with
# existing model faces
#
# of course, more code cleanup is in order
#

import sys
import re

import Blender
from Blender import Mathutils
from Blender import NMesh

substrate = '<LimbArray>'#'<twist:90><turn:90><LimbArray>'

# custom characters and their translations
custom = [ \
	('<Stem>', '<add:Stem><offset:0.5,0,0>'), \
	('<Joint2>', '<add:Joint2Start><offset:0.2,0,0><pitch:-30_0><add:Joint2Middle><turn:-20_20><add:Joint2End><offset:0.2,0,0>') \
	]

print "growing..."

# force recompile of ruleset
if 'ruleset' in sys.modules: del sys.modules['ruleset']
import ruleset

rules = [ (re.compile('<' + name + '(?::([^>]+))?>'), getattr(ruleset, name)) for name in dir(ruleset) ]

# do the matching
for stage in range(20):

	curPos = 0

	while True:
		newPos, newEnd = None, None
		newStr = None
		for regex, func in rules:
			match = regex.search(substrate, curPos)
			if match != None:
				if newPos == None or newPos > match.start():
					newPos = match.start()
					newEnd = match.end()
					newStr = func(match.group(1))

		if newPos == None: break

		substrate = substrate[:newPos] + newStr + substrate[newEnd:]
		curPos += len(newStr)
		
# translate custom chars
for char, repl in custom:
	substrate = re.sub(char, repl, substrate)

print "interpreting..."

# interpret the result
class StackFrame:

	# prev is the parent frame
	def __init__(self, prev=None):
		self.prev = prev
		if prev != None:
			self.matrix = prev.matrix
		else:
			self.matrix = Mathutils.Matrix()
			self.matrix.identity()
			self.matrix.resize4x4()

	# modifications
	def rotate(self, axis, angle):
		rot = Mathutils.RotationMatrix(angle, 4, axis)
		self.matrix = rot * self.matrix
	
	def offset(self, xyz):
		tra = Mathutils.TranslationMatrix(Mathutils.Vector(xyz))
		self.matrix = tra * self.matrix

	def scale(self, ratio):
		sca = Mathutils.Matrix( \
			[ ratio, 0, 0, 0 ], \
			[ 0, ratio, 0, 0 ], \
			[ 0, 0, ratio, 0 ], \
			[ 0, 0, 0, 1 ])
		self.matrix = sca * self.matrix
		
	# raises exception if no parent
	def getPrev(self):
		if self.prev == None:
			raise Exception, "no parent frames"
		return self.prev

	# appends current mesh to given one
	# does NOT change position
	def addMesh(self, meshObj, dest):
		mesh = meshObj.getData()

		vertBase = len(dest.verts)
		for v in mesh.verts:
			vec = Mathutils.Vector(v.co[0], v.co[1], v.co[2], 1)
			vec = vec*self.matrix
			cv = NMesh.Vert(vec.x, vec.y, vec.z)
			dest.verts.append(cv)

		for f in mesh.faces:
			cf = NMesh.Face([ dest.verts[v.index + vertBase] for v in f.v ])
			dest.addFace(cf)
	
		if mesh.edges != None:
			for e in mesh.edges:
				v1, v2 = e.v1, e.v2
				nv1, nv2 = dest.verts[v1.index + vertBase], dest.verts[v2.index + vertBase]
				ne = dest.addEdge(nv1, nv2)
				ne.crease = e.crease
		#dest.update()



# create result mesh
mesh = NMesh.New()
#mesh.addEdgesData() # for things like creases

# do the dew
frame = StackFrame()

# parses and interprets a string of type
# X:Y_Z (randomly choose either X or something between Y and Z)
def number(str):
	import random
	choices = str.split(':')
	choice = random.choice(choices)
	limits = choice.split('_', 2)
	if len(limits) == 2:
		return random.uniform(float(limits[0]), float(limits[1]))
	return float(limits[0])

instrMatch = re.compile(r"""
	<
		(?P<instr1>
			\w+
		)
		(?:
			:
			(?P<arg>
				[^>]+
			)
		)?
	>
	|
	(?P<instr2>
		[\[\]]
	)
	""", re.VERBOSE)
curPos = 0
while True:
	match = instrMatch.search(substrate, curPos)
	if match == None: break

	curPos = match.end()
	
	# collect instruction
	instr = match.group('instr1')
	if instr == None: instr = match.group('instr2')

	arg = match.group('arg')

	# do the dew
	if instr == "[":
		frame = StackFrame(frame)
	elif instr == "]":
		frame = frame.getPrev()
	elif instr == "offset":
		frame.offset([ number(a) for a in arg.split(',', 3) ])
	elif instr == "turn":
		frame.rotate("z", number(arg))
	elif instr == "pitch":
		frame.rotate("y", number(arg))
	elif instr == "twist":
		frame.rotate("x", number(arg))
	elif instr == "scale":
		frame.scale(number(arg))
	elif instr == "add":
		frame.addMesh(Blender.Object.Get(arg), mesh)

NMesh.PutRaw(mesh, "Result", 1, 1)


这个脚本显然不能在 blender 2.43 中工作,欢迎更新。

# Jamesk's Walk-o-matic version 0.49.9 (MODIFIED)
# for Blender 2.25 and a fully installed Python 2.0 [required]
# CHANGES FOR BLENDER 2.36 GENERALLY MARKED '#MDR:' ...
# Badly coded changes for Blender 2.43 by TwinStripe :) ! Appears to perform more passes but produces the same results!?!

# SET/CHECK THE PARAMETERS BELOW BEFORE EXECUTING THE SCRIPT.
# Make sure to select your proxy object, then run the script with ALT+P.
# Please consult the documentation for a full description of the parameters.
# ...Aaaaand check the console window for any messages.

# GENERAL SETTINGS:
FF = FIRST_FRAME = 1        # begin evaluating at this frame
LF = LAST_FRAME = 850       # stop evaluating after this frame

HS = HEEL_SEPARATION = 3.0  # desired distance between heel targets (in Blender Units)
MT = MOVE_TIME = 8.0        # number of frames/cycle a foot is moving
MSD = MOVE_STOP_DELAY = 0   # any value above zero will prolong the time a foot stays in the air.
HEEL_TO_FLAT_DISTANCE = 1   # desired distance between a heel target and its associated foot look-at-target
FLAT_TO_TLAT_DISTANCE = 0.5 # desired distance between a foot look-at-target and its associated toe look-at-target

AL = ALWAYS_LIFT = 0             # set to zero to prevent feet moving up/down when proxy has speed 0
CTD = C_TARG_DISTANCE = 2.0      # how far above proxy to place center target
LA = LIFT_AXIS = 'local'         # lift feet along global Z or local proxy Z?
CTDLA = CTD_LIFT_AXIS = 'global' # raise center target along global Z or local proxy Z?

# NAMES FOR THE EMPTIES:
HEEL_LEFT, HEEL_RIGHT = 'heel.ikt.left', 'heel.ikt.right' 
FLAT_LEFT, FLAT_RIGHT = 'foot.lat.left', 'foot.lat.right' 
TLAT_LEFT, TLAT_RIGHT = 'toe.lat.left', 'toe.lat.right'  
TARGET_CENTRE = 'target.centre'                    

# LIFT ENVELOPE SETTINGS:
LP = LIFT_PEAK = 0.5        # how far to lift above proxy initially 
FLATLP = FLAT_LIFT_PEAK = 0.2 # how far to lift foot look-at-target above proxy initially
TLATLP = TLAT_LIFT_PEAK = 0.2 # how far to lift toe look-at-target above proxy initially
LPT = LIFT_PEAK_TIME = 0.2  # time to reach lift-peak. (relative to movetime)

MP = MID_PEAK = 0.4         # how far from proxy after lift-peak
FLATMP = FLAT_MID_PEAK = 0.4 # how far to lift foot look-at-target
TLATMP = TLAT_MID_PEAK = 0.4 # how far to lift toe look-at-target
MPT = MID_PEAK_TIME = 0.5   # time to reach mid-peak (relative to movetime)

FP = FINAL_PEAK = 0.5       # how far from proxy before setting down again
FLATFP = FLAT_FINAL_PEAK = 0.7 # how far to lift foot look-at-target
TLATFP = TLAT_FINAL_PEAK = 0.9 # how far to lift toe look-at-target
FPT = FINAL_PEAK_TIME = 0.8 # time to reach final_peak (relative to - you guessed it - movetime)


#
# Concept and coding by James Kaufeldt a.k.a. Jamesk 
# Made in Sweden, november 2002
# Contact: [email protected]
#
# Special thanx to
# - [d0pamine] and [theeth] for some hints regarding vector math.
# - Martin [Strubi] Strubel from whom I borrowed the "normalize" function,
#   len3(x), dist3(x,y) and sub3(x,y) funcs found in his "vect.py" utility module.
# - [eeshlo] for pointing out how simple it was to give names to the empties.
#
# ---------------------------------------------------------------------------------------
# EDITABLE SECTION ENDS HERE!
#
# NO USER DEFINABLE VALUES BEYOND THIS POINT!
# ---------------------------------------------------------------------------------------
#
#
#
#

LT = MT
CT = MT + LT  

from Blender import Object, Scene, Window, Ipo
from Blender.Scene import Render
from Blender.Window import Types
import sys, math

proxy = Object.GetSelected()

status = 'UNDEFINED ERROR'
Layer = 0
print
print '----------------------------------'
print 'W A L K - O - M A T I C   V 0.49.9'
print '----------------------------------'
print
# make sure that there's an actual walker proxy to use:
if proxy == []:
    print 'No proxy indicated, terminating...'
    status = 'NO PROXY OBJECT SELECTED'
if proxy != []:
    proxy = proxy[0]
    print 'Proxy in use: \t',proxy
    Layer = proxy.Layer
    print ' in Layer',Layer
    status = 'OK'
sys.stdout.flush()

scene = Scene.GetCurrent()

# make sure there's a scene to use (should always be one, but wth...)
if scene == []:
    print 'No scene available, terminating...'
    status = 'NO CURRENT SCENE AVAILABLE'
if scene != []:
    print 'Target scene: \t',scene
sys.stdout.flush()

# some generally useful functions below:
def normalize(v):
    r = math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
    return (v[0]/r, v[1]/r, v[2]/r)

def len3(x):
    return math.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2])

def sub3(x, y):
    return ((x[0] - y[0]), (x[1] - y[1]), (x[2] - y[2]))

def dist3(x, y):
    return len3(sub3(x, y))

def moveAlong(origpos, distance, vector):
    newpos = [0,0,0]
    newpos[0] = origpos[0]+distance*vector[0]
    newpos[1] = origpos[1]+distance*vector[1]
    newpos[2] = origpos[2]+distance*vector[2]
    return newpos

def invertVector(v):
    return (-v[0], -v[1], -v[2])

#MDR:
def selectFrame(f):
    f = int(f)
    if scene.getRenderingContext().currentFrame() != f:
       scene.getRenderingContext().currentFrame(f)
       Window.Redraw(Window.Types.VIEW3D)

# MDR:
# Conversion routine:  try to get an object, return None if it's not there.
#   Just like Blender used to do.  The easiest way to accomplish this is to
#   allow the exception to occur, and catch it.

def TryGetObject(v):
  try:
    return Object.Get(v)
  except:
    return None


def getOffset(origin, frame, xdir, xdist, forward):
    # origin: the point to offset           frame: framenumber
    # xdir:  1 = positive offset along X, -1 = negative offset
    # xdist: how much to offset
    selectFrame(frame)
    loc = origin.getMatrix()[3]
    loc = moveAlong(loc, forward, normalize(origin.getMatrix()[1]))
    direction = normalize(origin.getMatrix()[0])
    if xdir == -1:
        direction = invertVector(direction)
    return moveAlong(loc, xdist, direction)

def getLiftAxisOffset(origin, frame, liftaxis, liftdist):
    # origin: the point to offset             frame: framenumber
    # liftaxis: 'global' or 'local' lifting   liftdist: the amount of lift    
    selectFrame(frame)
    loc = origin.getMatrix()[3]
    direction = normalize(origin.getMatrix()[2])
    if liftaxis=='global':
        direction = [0,0,1.0]
    return moveAlong(loc, liftdist, direction)

def getElevation(origin, frame, axis, zdist, xdir, xdist, forward):
    # origin: the point to offset     frame: framenumber
    # axis: 'local' or 'global'       zdist: how much to elevate
    # xdir: the X offset              xdist: the distance to offset along X
    loc = getOffset(origin, frame, xdir, xdist, forward)
    if axis=='local':
        direction = normalize(origin.getMatrix()[2])
        return moveAlong(loc, zdist, direction)
    if axis=='global':
        direction = [0, 0, 1.0]
        return moveAlong(loc, zdist, direction)
    
def writeCurvePoint(ipo, frame, point):
    # ipo: the IPOblock to use           frame: at what frame
    # point: the 3D coordinate to write
    xc = ipo.getCurve('LocX')
    yc = ipo.getCurve('LocY')
    zc = ipo.getCurve('LocZ')
    for idx, c in enumerate([xc,yc,zc]):
        c.addBezier((frame, point[idx]))
        c.update()
     
def makeIPO(name, ipol, expol):
    # name: desired name for this IPOblock    ipol: type of interpolation
    # expol: type of extrapolation
    ipo = Ipo.New('Object', name)
    xc = ipo.addCurve('LocX')
    yc = ipo.addCurve('LocY')
    zc = ipo.addCurve('LocZ')
    for curve in [xc, yc, zc]:
        curve.setInterpolation(ipol)
        curve.setExtrapolation(expol)
    return ipo

def move(ipo, origin, destination, startframe, framespan, proxob, xdir, xdist, forward):
    # ipo - what ipo to write points to                 origin - the location (3Dpoint) to start at
    # destination - the location to end up at           startframe - frame to set the first curvepoint at
    # framespan - total number of frames for the move   proxob - the proxy/reference object
    # xdir - pos or neg offset along proxy X-axis       xdist - how much to offset along proxy X-axis
    writeCurvePoint(ipo, startframe, origin)

    if AL==1 or origin!=destination:
        # Write curvepoints for LiftPeak and LiftPeakTime:
        # Pretty hackish formulae for proxyTime here... But they do work, so wtf...
        lpProxyTime = startframe + (LPT*framespan*2)-framespan*0.25
        lpRealTime = startframe+(framespan+MSD)*LPT
        lpLocation = getElevation(proxob, lpProxyTime, LA, LP, xdir, xdist, forward)
        writeCurvePoint(ipo, lpRealTime, lpLocation)
        # Write curvepoints for MidPeak and MidPeakTime:
        mpProxyTime = startframe + (MPT*framespan*2)-framespan*0.25
        mpRealTime = startframe+(framespan+MSD)*MPT
        mpLocation = getElevation(proxob, mpProxyTime, LA, MP, xdir, xdist, forward)
        writeCurvePoint(ipo, mpRealTime, mpLocation)
        # Write curvepoints for FinalPeak and FinalPeakTime:
        fpProxyTime = startframe + (FPT*framespan*2)-framespan*0.25
        fpRealTime = startframe+(framespan+MSD)*FPT
        fpLocation = getElevation(proxob, fpProxyTime, LA, FP, xdir, xdist, forward)
        writeCurvePoint(ipo, fpRealTime, fpLocation)
    
    writeCurvePoint(ipo, startframe+framespan+MSD, destination)
    return (startframe+framespan, destination)

def hold(ipo, location, startframe, framespan):
    # ipo - what ipo to write points to                 # location - the position (3Dpoint) to hold at
    # startframe - the first frame in the hold sequence # framespan - total number of frames to hold
    writeCurvePoint(ipo, startframe+MSD, location)
    writeCurvePoint(ipo, startframe+framespan, location)
    return (startframe+framespan, location)

def recalculator(assignedTargets, targ1, targ2, basetarg):
    # rewrites some globals based on the current arrangement of the empties:
    loc1 = targ1.getLocation()
    loc2 = targ2.getLocation()
    loc3 = basetarg.getLocation()
    # HEEL_SEPARATION:
    if assignedTargets=='heels':
        print 'Default heel empties found. Recalculating:'
        global HS
        HS = dist3(loc1, loc2)
        print 'HEEL_SEPARATION set to',HS
    if assignedTargets=='flats':
        print 'Default foot look-at targets found. Reusing.'
        global HEEL_TO_FLAT_DISTANCE
        HEEL_TO_FLAT_DISTANCE = dist3(loc2, loc3)
        print 'HEEL_TO_FLAT_DISTANCE set to', HEEL_TO_FLAT_DISTANCE
    if assignedTargets=='tlats':
        print 'Default toe look-at targets found. Reusing.'
        global FLAT_TO_TLAT_DISTANCE
        FLAT_TO_TLAT_DISTANCE = dist3(loc2, loc3)
        print 'FLAT_TO_TLAT_DISTANCE set to',FLAT_TO_TLAT_DISTANCE
    

def doIt(forwardOffset, addCenter, whatsUp, firstName, secondName):
    print
    print 'Currently processing:',whatsUp
    # Start building the IPO for the right foot:
    ffootipo = makeIPO('rfoot', 'Linear', 'Constant')
    cpf = currentProxyFrame = FF

    # make first step (only half as far as the others):
    ffootloc = getOffset(proxy, cpf, 1, HS/2, forwardOffset)
    ffootframe = cpf
    targetloc = getOffset(proxy, cpf+MT, 1, HS/2, forwardOffset)
    ffootframe, ffootloc = move(ffootipo, ffootloc, targetloc, ffootframe, MT/2,proxy, 1, HS/2, forwardOffset)
    ffootframe, ffootloc = hold(ffootipo, ffootloc, ffootframe, LT)

    # now make the rest of the steps (full length):
    while True:
        cpf += CT
        targetloc = getOffset(proxy, cpf+MT, 1, HS/2, forwardOffset)
        ffootframe, ffootloc = move(ffootipo, ffootloc, targetloc, ffootframe, MT,proxy, 1, HS/2, forwardOffset)
        ffootframe, ffootloc = hold(ffootipo, ffootloc, ffootframe, LT)
        if cpf>LF:
            break
   
    # Then we'll build the IPO for the left foot:
    sfootipo = makeIPO('lfoot', 'Linear', 'Constant')
    cpf = currentProxyFrame = FF

    # this one starts in hold-mode (waits for right foot to finish)
    sfootloc = getOffset(proxy, cpf, -1, HS/2, forwardOffset)
    sfootframe = cpf
    sfootframe, sfootloc = hold(sfootipo, sfootloc, cpf, MT/2)

    while True:
        cpf += CT
        targetloc = getOffset(proxy, cpf, -1, HS/2, forwardOffset)
        sfootframe, sfootloc = move(sfootipo, sfootloc, targetloc, sfootframe, MT,proxy, -1, HS/2, forwardOffset)
        sfootframe, sfootloc = hold(sfootipo, sfootloc, sfootframe, LT)
        if cpf>LF:
            break

    if addCenter:
        # And to finish it off, let's put something in the middle of this:
        # This will simply add a third target floating above the proxy.
        # It will respect the specified lift axis, hence useful as parent for an armature
        ctargetipo = makeIPO('center', 'Linear', 'Constant')
        for cframe in range(FF, LF):
            targetloc = getLiftAxisOffset(proxy, cframe, CTDLA, CTD)
            writeCurvePoint(ctargetipo, cframe, targetloc)

    # Finished. Add or reuse empties and link them to their respective IPOblocks.
    leftikt = TryGetObject(firstName)
    leftnew = False
    if leftikt==None:
        leftikt = Object.New('Empty')
        leftnew = True
        
    rightikt = TryGetObject(secondName)
    rightnew = False
    if rightikt==None:
        rightikt = Object.New('Empty')
        rightnew = True
    leftikt.name = firstName
    rightikt.name = secondName
    print 'Targets',leftikt,rightikt
    if addCenter:
        centertarget = TryGetObject(TARGET_CENTRE)
        centernew = False
        if centertarget==None:
            centertarget = Object.New('Empty')
            centernew = True
        centertarget.name = TARGET_CENTRE
        print 'Centertarget',centertarget
        centertarget.Layer = Layer
        if centernew: 
			scene.link(centertarget)
		
	    #MDR: 'SetIPO' was 'link'...
        centertarget.setIpo(ctargetipo)
    leftikt.Layer = Layer
    rightikt.Layer = Layer
    if leftnew: 
		scene.link(leftikt)
    if rightnew: 
		scene.link(rightikt)
		
	#MDR: Ditto... 'setIpo' was 'link'...
    leftikt.setIpo(sfootipo)
    rightikt.setIpo(ffootipo)
    print whatsUp,'IPO:s',sfootipo,ffootipo
    print '---------------------------------------------------------'
    sys.stdout.flush()
    


#########################################
# if everything's OK, let's get to work #
#########################################
if status=='OK':
    currentUserFrame = scene.getRenderingContext().currentFrame()

    # grab any walkomat empties left in the scene:
    oldleftheel =TryGetObject(HEEL_LEFT)
    oldrightheel =TryGetObject(HEEL_RIGHT)

    oldleftflat =TryGetObject(FLAT_LEFT)
    oldrightflat =TryGetObject(FLAT_RIGHT)

    oldlefttlat =TryGetObject(TLAT_LEFT)
    oldrighttlat=TryGetObject(TLAT_RIGHT)

    emptyipo = makeIPO('emptydummy', 'Linear', 'Constant')

    # recalculate if there were any such empties:
    if oldleftheel!=None and oldrightheel!=None:
        # assign an empty IPO first to clear any anim:
        # why isn't there some 'unlink' function somewhere???
        #
        # MDR: These 'setIpo' calls were 'link' ....
        #
        oldleftheel.setIpo(emptyipo)
        oldrightheel.setIpo(emptyipo)
        recalculator('heels', oldleftheel, oldrightheel, oldrightheel)

    if oldleftflat!=None and oldrightflat!=None:
        oldleftflat.setIpo(emptyipo)
        oldrightflat.setIpo(emptyipo)
        recalculator('flats', oldleftflat, oldrightflat, oldrightheel)

    if oldlefttlat!=None and oldrighttlat!=None:
        oldlefttlat.setIpo(emptyipo)
        oldrighttlat.setIpo(emptyipo)
        recalculator('tlats', oldlefttlat, oldrighttlat, oldrightflat)

    # first pass, heel targets:
    doIt(0, 1, 'Heel targets', HEEL_LEFT, HEEL_RIGHT)

    #second pass, foot look-at targets:
    LP = FLATLP
    MP = FLATMP
    FP = FLATFP
    doIt(HEEL_TO_FLAT_DISTANCE, 0, 'Foot look-at targets', FLAT_LEFT, FLAT_RIGHT)

    #third pass, toe look-at targets:
    LP = TLATLP
    MP = TLATMP
    FP = TLATFP
    doIt(HEEL_TO_FLAT_DISTANCE+FLAT_TO_TLAT_DISTANCE, 0, 'Toe look-at targets', TLAT_LEFT, TLAT_RIGHT)

    # At last, as a friendly gesture, restore the frame to whatever the user
    # was looking at before running the script, and refresh the screens:  
    scene.getRenderingContext().currentFrame(currentUserFrame)
    Window.RedrawAll()
    print 'Processing completed.'
    print 'Thank you for using Walk-O-Matic :D'
    sys.stdout.flush()

    
###################################################
# if things are not right, print some dying words:#
###################################################
if status!='OK':
    print ''
    print 'Walk-o-matic is sadly forced to report that'
    print 'it could not go to work properly.'
    print 'Cause of termination: ',status
    print 'Please consult the documentation regarding proper use.'
    sys.stdout.flush()
华夏公益教科书