2000-11-27 18:28:20 +00:00
|
|
|
#This file is distributed under the terms of the GNU General Public license.
|
|
|
|
|
#Copyright (C) 1999 Aloril (See the file COPYING for details).
|
|
|
|
|
|
|
|
|
|
from types import *
|
|
|
|
|
from atlas import *
|
|
|
|
|
from common import log
|
|
|
|
|
|
2006-12-12 Al Riddoch <alriddoch@zepler.org>
* configure.ac: Increment version.
* common/const.h: Declare a doxygen group for all the consts.
* common/operations.cpp, common/Add.h, common/Attack.h, common/Burn.h,
common/Chop.h, common/Connect.h, common/Cut.h, common/Delve.h,
common/Dig.h, common/Drop.h, common/Eat.h, common/Monitor.h,
common/Mow.h, common/Nourish.h, common/Pickup.h, common/Setup.h,
common/Tick.h, common/Unseen.h, common/Update.h:
Declare a doxygen group for all custom operations.
* rulesets/Area.h, rulesets/Character.h, rulesets/Creator.h,
rulesets/Entity.h, rulesets/Food.h, rulesets/Line.h,
rulesets/Missile.h, rulesets/Plant.h, rulesets/Stackable.h,
rulesets/Structure.h, rulesets/World.h: Declare a doxygen group
for in game entity classses.
* common/Property.h, common/Property_impl.h, server/ScriptFactory.cpp,
server/ScriptFactory.h, server/SlaveClientConnection.cpp,
server/SlaveClientConnection.h: Add some more inlined documentation.
2006-12-12 15:54:20 +00:00
|
|
|
## \defgroup PythonGoals Goal Classes
|
|
|
|
|
|
|
|
|
|
## \brief Base class for all goals
|
|
|
|
|
## \ingroup PythonGoals
|
2000-11-27 18:28:20 +00:00
|
|
|
class Goal:
|
|
|
|
|
def __init__(self,desc="some goal",fulfilled=None,subgoals=[],
|
2016-06-08 22:03:59 +02:00
|
|
|
validity=None,time=None, debug=0):
|
2000-11-27 18:28:20 +00:00
|
|
|
self.desc=desc
|
|
|
|
|
#mind sets these:
|
|
|
|
|
#self.str
|
|
|
|
|
#self.key
|
2016-03-30 22:34:44 +02:00
|
|
|
if fulfilled:
|
|
|
|
|
self.fulfilled = fulfilled
|
|
|
|
|
else:
|
|
|
|
|
self.fulfilled = lambda me:0 #false
|
2016-06-08 22:03:59 +02:00
|
|
|
|
|
|
|
|
#If no validity function is supplied the goal is always considered valid
|
|
|
|
|
if validity:
|
|
|
|
|
self.validity = validity
|
|
|
|
|
else:
|
|
|
|
|
self.validity = lambda me:True
|
|
|
|
|
|
2000-11-27 18:28:20 +00:00
|
|
|
self.subgoals=subgoals[:]
|
|
|
|
|
self.time=time
|
|
|
|
|
self.debug=debug
|
|
|
|
|
self.vars=[]
|
2013-04-01 22:17:58 +02:00
|
|
|
#keeps track of whether the goal is fulfilled or not
|
|
|
|
|
#this is mainly of use for inspection and diagnosis
|
|
|
|
|
self.is_fulfilled=0
|
2000-11-27 18:28:20 +00:00
|
|
|
#any subgoal/function/method can set this and
|
|
|
|
|
#it's checked at start of check_goal_rec
|
|
|
|
|
#and NPCMind.py fulfill_goals uses it too to remove goals from list
|
|
|
|
|
self.irrelevant=0
|
2013-04-07 23:18:29 +02:00
|
|
|
#Tracks the number of errors this goal (or any of its subgoals) has produced.
|
|
|
|
|
#This is used by NPC code to remove troublesome goals from the processing
|
|
|
|
|
self.errors=0
|
|
|
|
|
#If an error has occurred, the description of the last one is stored here.
|
|
|
|
|
#This is mainly of use for debugging.
|
|
|
|
|
self.lastError=""
|
2007-09-06 22:17:57 +00:00
|
|
|
def __repr__(self):
|
|
|
|
|
return self.info()
|
2000-11-27 18:28:20 +00:00
|
|
|
def info(self):
|
|
|
|
|
name=self.__class__.__name__
|
|
|
|
|
if name=="Goal":
|
|
|
|
|
return name+"("+`self.desc`+")"
|
|
|
|
|
var=""
|
|
|
|
|
for v in self.vars:
|
|
|
|
|
if var: var=var+","
|
|
|
|
|
var=var+`getattr(self,v)`
|
|
|
|
|
return name+"("+var+")"
|
2016-06-08 22:03:59 +02:00
|
|
|
def is_valid(self, me):
|
|
|
|
|
"""Checks if this goal is valid. By this we mean whether the goal is possible to fulfill.
|
|
|
|
|
If no validity function was supplied at goal creation time the goal is always considered valid. """
|
|
|
|
|
return self.validity(me)
|
|
|
|
|
|
2000-11-27 18:28:20 +00:00
|
|
|
def check_goal(self, me, time):
|
|
|
|
|
"executes goal, see top of file"
|
|
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("GOAL desc: "+self.str)
|
2013-05-29 23:23:27 +02:00
|
|
|
res,debugInfo=self.check_goal_rec(me,time,0,"")
|
|
|
|
|
if len(debugInfo)!=0:
|
|
|
|
|
#Keep a copy of the debug info for the "report" method.
|
|
|
|
|
self.lastProcessedGoals=debugInfo
|
2000-11-27 18:28:20 +00:00
|
|
|
if res!=None:
|
2013-05-29 23:23:27 +02:00
|
|
|
info_ent=Entity(op=res,description=debugInfo)
|
2000-11-27 18:28:20 +00:00
|
|
|
return res+Operation("goal_info",info_ent)
|
2013-05-29 23:23:27 +02:00
|
|
|
def check_goal_rec(self, me, time, depth, debugInfo):
|
2013-05-29 22:14:29 +02:00
|
|
|
"""check (sub)goal recursively.
|
|
|
|
|
|
|
|
|
|
This is done by iterating over all subgoals, breaking if any subgoal returns an operation."""
|
2013-05-29 23:23:27 +02:00
|
|
|
res=None
|
|
|
|
|
if self.irrelevant: return res,debugInfo
|
2000-11-27 18:28:20 +00:00
|
|
|
#is it right time range?
|
2013-05-29 23:23:27 +02:00
|
|
|
if self.time and not time.is_now(self.time): return res,debugInfo
|
2000-11-27 18:28:20 +00:00
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: bef fulfilled: "+self.desc+" "+`self.fulfilled`)
|
2013-04-01 22:17:58 +02:00
|
|
|
if self.fulfilled(me):
|
|
|
|
|
self.is_fulfilled = 1
|
2013-05-29 22:14:29 +02:00
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: is fulfilled: "+self.desc+" "+`self.fulfilled`)
|
2013-05-29 23:23:27 +02:00
|
|
|
return res,debugInfo
|
2013-04-01 22:17:58 +02:00
|
|
|
else:
|
2013-05-29 22:14:29 +02:00
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: is not fulfilled: "+self.desc+" "+`self.fulfilled`)
|
2013-04-01 22:17:58 +02:00
|
|
|
self.is_fulfilled = 0
|
2013-05-29 23:23:27 +02:00
|
|
|
debugInfo=debugInfo+"."+self.info()
|
2013-05-29 22:14:29 +02:00
|
|
|
#Iterate over all subgoals, but break if any goal returns an operation
|
2000-11-27 18:28:20 +00:00
|
|
|
for sg in self.subgoals:
|
2016-03-30 22:34:44 +02:00
|
|
|
if sg == None:
|
|
|
|
|
continue
|
2000-11-27 18:28:20 +00:00
|
|
|
if type(sg)==FunctionType or type(sg)==MethodType:
|
2013-05-29 22:30:57 +02:00
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: bef function: "+`sg`+" "+`res`)
|
2000-11-27 18:28:20 +00:00
|
|
|
res=sg(me)
|
2013-05-29 22:30:57 +02:00
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: aft function: "+`sg`+" "+`res`)
|
2013-05-29 23:23:27 +02:00
|
|
|
debugInfo=debugInfo+"."+sg.__name__+"()"
|
2013-05-29 22:30:57 +02:00
|
|
|
if res!=None:
|
|
|
|
|
#If the function generated an op, stop iterating here and return
|
2013-05-29 23:23:27 +02:00
|
|
|
return res,debugInfo
|
2000-11-27 18:28:20 +00:00
|
|
|
else:
|
|
|
|
|
if self.debug:
|
|
|
|
|
log.thinking("\t"*depth+"GOAL: bef sg: "+sg.desc)
|
2013-05-29 23:23:27 +02:00
|
|
|
res,debugInfo=sg.check_goal_rec(me,time,depth+1,debugInfo)
|
2000-11-27 18:28:20 +00:00
|
|
|
if self.debug:
|
2013-05-29 22:14:29 +02:00
|
|
|
log.thinking("\t"*depth+"GOAL: aft sg: "+sg.desc+", Result: "+str(res))
|
|
|
|
|
#If the subgoal generated an op, stop iterating here and return
|
|
|
|
|
if res!=None:
|
2013-05-29 23:23:27 +02:00
|
|
|
return res,debugInfo
|
|
|
|
|
return res,debugInfo
|
2013-04-01 22:17:58 +02:00
|
|
|
|
|
|
|
|
def report(self):
|
|
|
|
|
"""provides extended information about the goal,
|
|
|
|
|
as well as all subgoals"""
|
|
|
|
|
name=self.__class__.__name__
|
|
|
|
|
map={}
|
|
|
|
|
map["name"]=name
|
|
|
|
|
map["description"]=self.desc
|
|
|
|
|
map["fulfilled"]=self.is_fulfilled
|
2013-05-29 23:23:46 +02:00
|
|
|
if hasattr(self, "lastProcessedGoals"):
|
|
|
|
|
map["lastProcessedGoals"] = self.lastProcessedGoals
|
2013-04-01 22:17:58 +02:00
|
|
|
|
2013-05-29 23:23:46 +02:00
|
|
|
if len(self.subgoals) > 0:
|
|
|
|
|
subgoals=[]
|
|
|
|
|
for sg in self.subgoals:
|
2016-06-08 21:44:33 +02:00
|
|
|
if type(sg)!=FunctionType and type(sg)!=MethodType and sg is not None:
|
2013-05-29 23:23:46 +02:00
|
|
|
subgoals.append(sg.report())
|
|
|
|
|
map["subgoals"]=subgoals
|
2013-04-01 22:17:58 +02:00
|
|
|
|
2013-05-29 23:23:46 +02:00
|
|
|
if len(self.vars) > 0:
|
|
|
|
|
variables={}
|
|
|
|
|
for v in self.vars:
|
|
|
|
|
variables[v]=str(getattr(self,v))
|
|
|
|
|
map["variables"]=variables
|
2013-04-07 23:18:29 +02:00
|
|
|
|
|
|
|
|
if self.errors > 0:
|
|
|
|
|
map["errors"]=self.errors
|
|
|
|
|
map["lastError"]=self.lastError
|
2013-04-01 22:17:58 +02:00
|
|
|
return map
|
|
|
|
|
|