def handle_OPENDOOR(self, action, data, id): dir = data.lower() if not G.rooms[self.char.loc].open[dir]: G.rooms[self.char.loc].open[dir] = True px, py, pz = self.char.loc mx, my, mz = Constant.sdirections[dir] G.rooms[(px+mx,py+my,pz+mz)].open[Constant.invert[dir]] = True coms.sendRoom(self.char.loc, Ascii.C.format % ("gray", "The door to the %s opens." % (Constant.tolong[dir],)), []) coms.sendRoom((px+mx,py+my,pz+mz), Ascii.C.format % ("gray", "The door to the %s opens." % (Constant.tolong[Constant.invert[dir]],)), [])
def AIBrain(self): startt = time.time() cm = self.cm # adjust our think time depending if we have agro until we no longer have agro # check if there are people in the room with us # if we are ranged check if there are people within range if self.cm.isdead: ##### Dead (5 second think time) # we are dead, put us to sleep self.sleep() else: ##### AGRO CHECK if not self.cm.agro: self.addAgroRoom() agro = {} # sort a list of targets, apply our modifier and choose the highest on my list for target, value in cm.agro.iteritems(): # treat things in the room with us as 150% agro agro[target] = (value * 1.5) if (G.chars[target].loc if target in G.chars else G.monster_live[target].loc) == cm.loc else value agros = sorted(agro.iteritems(), key=operator.itemgetter(1)) ##### Check to see if we want to move if not len(agros) and not self.cm.dir and (random.randint(1,100) <= int(self.cm.wander * 100)): # wander dirs = [] for dir in G.rooms[self.cm.loc].exit: if G.rooms[self.cm.loc].exit[dir] == 1: dirs.append(dir) if dirs: random.shuffle(dirs) dir = dirs.pop() self.DoMove((Constant.tolong[dir], None)) acted = False while not acted and len(agros): target, value = agros.pop() target = (G.chars[target] if target in G.chars else G.monster_live[target]) if target.isdead or target.state == CState.OFFLINE: logging.debug("AI; monster %s (%s); target; %s; dead or offline", cm.m.name, cm.uid, target.name) continue else: for e in target.effects: if "SYSINVIS" in e.adjust: char.hideDC = 666 break if target.hideDC == 0 or (target.hideDC <= self.cm.rollSkill("perception", 5)): logging.debug("AI; monster %s (%s); target; %s; in combat; %s", cm.m.name, cm.uid, target.name, cm.incombat) else: logging.debug("AI; monster %s (%s); target; %s; in combat; %s; target hidden", cm.m.name, cm.uid, target.name, cm.incombat) continue if target.name in G.chars or target.uid in G.monster_live: # check rooms mx, my, mz = cm.loc px, py, pz = target.loc for dir, add in Constant.sdirections.iteritems(): if (cm.loc == target.loc): if cm.target != (target.name if target.__class__.__name__ == 'char' else target.uid) or not cm.incombat: ##### Target this player cm.target = (target.name if target.__class__.__name__ == 'char' else target.uid) cm.incombat = True cm.engaged = True cm.cround = G.round target.incombat = True target.avatar.protocol.sendStat.combat(target.avatar.protocol, True) if not target.target: target.target = cm.uid target.cround = G.round # send a moves to attack message to the room logging.debug("AI; monster %s (%s); attacking; %s", cm.m.name, cm.uid, target.name) self.RoomMessage("%s %s %s moves to attack %s!" % (cm.dsc, cm.pname, cm.m.name, target.name), cm.loc, (target.avatar,)) self.DirectMessage("%s %s %s moves to attack you!" % (cm.dsc, cm.pname, cm.m.name), target) # parse spells for chance, s in cm.m.spells: self.DoSpell(s, chance) acted = True break ax, ay, az = add if G.rooms[cm.loc].exit[dir] and ((mx+ax == px and my+ay == py and mz+az == pz)) and G.rooms[(mx+ax,my+ay,mz+az)].areaid == cm.area: # Don't move if you are ranged if not cm.m.reach: logging.debug("AI; monster %s (%s); found target; %s; adjacent room %s; moving", cm.m.name, cm.uid, target.name, Constant.tolong[dir]) acted = self.DoMove((Constant.tolong[dir], target)) else: logging.debug("AI; monster %s (%s); found target; %s; adjacent room %s; reach; %s", cm.m.name, cm.uid, target.name, Constant.tolong[dir], cm.m.reach) if (not cm.target or not cm.target == target.name or not cm.incombat): acted = True # target this player from a range cm.target = target.name cm.incombat = True cm.engaged = True cm.cround = G.round target.cround = G.round target.incombat = True target.avatar.protocol.sendStat.combat(target.avatar.protocol, True) if not target.target: target.target = cm.uid # send a moves to attack message to the room logging.debug("AI; monster %s (%s); attacking ranged; %s; %s", cm.m.name, cm.uid, Constant.tolong[dir].title(), target.name) dsc = "an" if (cm.pname and cm.pname[0].lower() in Constant.vowels) else "a" self.RoomMessage("%s %s %s moves to attack %s, to the %s!" % (dsc, cm.pname, cm.m.name, target.name, Constant.tolong[dir].title()), cm.loc, (target.avatar,)) self.DirectMessage("%s %s %s moves to attack you, from the %s!" % (dsc, cm.pname, cm.m.name, Constant.invert(Constant.tolong[dir])), target) # parse spells for s, chance in cm.m.spells: self.DoSpell(s, chance) break # try to follow their tracks (we need to be smart to track) else: if G.tracks.has_key(cm.loc): for name, dir, round in G.tracks[cm.loc]: if name == target.name: # DC is 5 * rounds old # basic track score is d10 + (ING * 2) so -2 is 6 (1 round) and +5 is 20 (3 rounds) if int(random.randint(1, 10) + (cm.m.stat["ING"] * 2)) >= int((G.round - round) * 5): # found you bitch logging.debug("AI; monster %s (%s); following tracks; %s; %s", cm.m.name, cm.uid, dir, target.name) acted = self.DoMove((dir, target)) break else: logging.debug("AI; monster %s (%s); lost trail; %s", cm.m.name, cm.uid, target.name) if acted: break if not acted and not cm.incombat and self.awake: if cm.srounds < 2: cm.srounds += 1 logging.debug("AI; We didn't act, strike %s", cm.srounds) else: # umm, I lost the trail # are we at home? if not cm.loc == cm.sloc: # start walking back home if not cm.dir: mstartt = time.time() maze = {} for key, r in G.rooms.iteritems(): if r.areaid == G.rooms[cm.sloc].areaid: maze[key] = r ms = MazeSolver(maze) solved_maze = ms.Astar(cm.loc, cm.sloc) cm.dir = solved_maze mendt = time.time() logging.debug("AI; Calculated directions home in %.6f seconds; %s", (mendt - mstartt), solved_maze) dir = cm.dir.pop(0) self.DoMove((dir, None)) else: logging.debug("AI; Directions left; %s", cm.dir) dir = cm.dir.pop(0) self.DoMove((dir, None)) else: if self.awake == True: #reset us self.cm.reset() self.sleep() # we reset and we were forced spawned, destroy us if not self.cm.spawn_chance: self.cm.isdead = True coms.sendRoom(self.cm.loc, self.cm.m.message["death"].text % (self.cm.name,)) else: cm.srounds = 0 #reset our idle rounds
def doChain(self, chain=None): # is there text in this chain? nextlink = None chain = chain if chain else self.start if chain.text and chain.words: self.msg = chain.text if chain.rmsg and chain.words: self.rmsg = chain.rmsg # % (Ascii.C.format % ("bwhite", self.char.name)) if chain.text and not chain.words: if self.monster: self.char.avatar.protocol.sendLine(Ascii.C.format % ("gray", "%s says, '%s'" % (self.monster.name, chain.text)), True) else: self.char.avatar.protocol.sendLine(Ascii.C.format % ("gray", "%s" % (chain.text))) self.default = False if chain.rmsg and not chain.words: if self.monster: coms.sendRoom(self.char.loc, Ascii.C.format % ("gray", "%s says to %s, '%s'" % (self.monster.name, Ascii.C.format % ("bwhite", self.char.name), chain.rmsg)), [self.char.avatar,], True) else: coms.sendRoom(self.char.loc, Ascii.C.format % ("gray", chain.rmsg % (Ascii.C.format % ("bwhite", self.char.name))), [self.char.avatar,]) self.default = False # grab the words and store them if chain.words: for word in chain.words.split(","): w, sep, link = word.partition(":") self.words.append((w,int(link))) if chain.test: try: thetest = eval(chain.test,{"__builtins__":None},{"char":self.char,"room":G.rooms[self.char.loc]}) logging.debug("dialogchain; %s; %s; eval; %s", chain.id, chain.test, thetest) except Exception as e: logging.debug("dialogchain; %s; %s; except; %s", chain.id, chain.test, e.args) thetest = False if thetest and chain.tpass: self.doLink(chain.tpass, chain.id) elif not thetest and chain.tfail: self.doLink(chain.tfail, chain.id) # check for a keyword match if self.keyword and not self.kwmatch: for word, link in self.words: if word.startswith(self.keyword): # clear our message, we should follow a keyword self.kwmatch = True self.doLink("dialogchain %s;" % (link,), chain.id) break elif chain == self.start and self.default: if self.monster: self.char.avatar.protocol.sendLine(Ascii.C.format % ("gray", "%s says, '%s'" % (self.monster.name, self.msg)), True) coms.sendRoom(self.char.loc, Ascii.C.format % ("gray", "%s says to %s, '%s'" % (self.monster.name, Ascii.C.format % ("bwhite", self.char.name), self.rmsg)), [self.char.avatar,], True) else: if self.msg: self.char.avatar.protocol.sendLine(Ascii.C.format % ("gray", "%s" % (self.msg))) if self.rmsg: coms.sendRoom(self.char.loc, Ascii.C.format % ("gray", self.rmsg % (Ascii.C.format % ("bwhite", self.char.name))), [self.char.avatar,]) logging.debug("dialogchain; %s; end", chain.id) return self.kwmatch