Fixing tutorial world usage of search.

This commit is contained in:
Griatch 2012-09-27 21:36:20 +02:00
parent 59ccd3eb38
commit 1b0544c261
3 changed files with 227 additions and 227 deletions

View file

@ -1,7 +1,7 @@
"""
This module implements a simple mobile object with
This module implements a simple mobile object with
a very rudimentary AI as well as an aggressive enemy
object based on that mobile class.
object based on that mobile class.
"""
@ -16,10 +16,10 @@ BASE_CHARACTER_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
#------------------------------------------------------------
#
# Mob - mobile object
# Mob - mobile object
#
# This object utilizes exits and moves about randomly from
# room to room.
# room to room.
#
#------------------------------------------------------------
@ -27,7 +27,7 @@ class Mob(tut_objects.TutorialObject):
"""
This type of mobile will roam from exit to exit at
random intervals. Simply lock exits against the is_mob attribute
to block them from the mob (lockstring = "traverse:not attr(is_mob)").
to block them from the mob (lockstring = "traverse:not attr(is_mob)").
"""
def at_object_creation(self):
"This is called when the object is first created."
@ -35,11 +35,11 @@ class Mob(tut_objects.TutorialObject):
self.scripts.add(tut_scripts.IrregularEvent)
# this is a good attribute for exits to look for, to block
# a mob from entering certain exits.
self.db.is_mob = True
self.db.last_location = None
# only when True will the mob move.
self.db.roam_mode = True
# a mob from entering certain exits.
self.db.is_mob = True
self.db.last_location = None
# only when True will the mob move.
self.db.roam_mode = True
def announce_move_from(self, destination):
"Called just before moving"
@ -53,8 +53,8 @@ class Mob(tut_objects.TutorialObject):
"Called at irregular intervals. Moves the mob."
if self.roam_mode:
exits = [ex for ex in self.location.exits if ex.access(self, "traverse")]
if exits:
# Try to make it so the mob doesn't backtrack.
if exits:
# Try to make it so the mob doesn't backtrack.
new_exits = [ex for ex in exits if ex.destination != self.db.last_location]
if new_exits:
exits = new_exits
@ -67,15 +67,15 @@ class Mob(tut_objects.TutorialObject):
#------------------------------------------------------------
#
# Enemy - mobile attacking object
# Enemy - mobile attacking object
#
# An enemy is a mobile that is aggressive against players
# in its vicinity. An enemy will try to attack characters
# An enemy is a mobile that is aggressive against players
# in its vicinity. An enemy will try to attack characters
# in the same location. It will also pursue enemies through
# exits if possible.
# exits if possible.
#
# An enemy needs to have a Weapon object in order to
# attack.
# An enemy needs to have a Weapon object in order to
# attack.
#
# This particular tutorial enemy is a ghostly apparition that can only
# be hurt by magical weapons. It will also not truly "die", but only
@ -90,44 +90,44 @@ class AttackTimer(Script):
"""
def at_script_creation(self):
"This sets up the script"
self.key = "AttackTimer"
self.key = "AttackTimer"
self.desc = "Drives an Enemy's combat."
self.interval = random.randint(2, 3) # how fast the Enemy acts
self.interval = random.randint(2, 3) # how fast the Enemy acts
self.start_delay = True # wait self.interval before first call
self.persistent = True
self.persistent = True
def at_repeat(self):
"Called every self.interval seconds."
"Called every self.interval seconds."
if self.obj.db.inactive:
return
return
#print "attack timer: at_repeat", self.dbobj.id, self.ndb.twisted_task, id(self.ndb.twisted_task)
if self.obj.db.roam_mode:
if self.obj.db.roam_mode:
self.obj.roam()
#return
elif self.obj.db.battle_mode:
#print "attack"
self.obj.attack()
return
return
elif self.obj.db.pursue_mode:
#print "pursue"
self.obj.pursue()
#return
else:
#dead mode. Wait for respawn.
#dead mode. Wait for respawn.
dead_at = self.db.dead_at
if not dead_at:
self.db.dead_at = time.time()
if (time.time() - self.db.dead_at) > self.db.dead_timer:
self.obj.reset()
class Enemy(Mob):
"""
This is a ghostly enemy with health (hit points). Their chance to hit, damage etc is
determined by the weapon they are wielding, same as characters.
An enemy can be in four modes:
An enemy can be in four modes:
roam (inherited from Mob) - where it just moves around randomly
battle - where it stands in one place and attacks players
battle - where it stands in one place and attacks players
pursue - where it follows a player, trying to enter combat again
dead - passive and invisible until it is respawned
@ -139,19 +139,19 @@ class Enemy(Mob):
defeat_text_room - text to show other players in room when a player is defeated
win_text - text to show player when defeating the enemy
win_text_room - text to show room when a player defeates the enemy
respawn_text - text to echo to room when the mob is reset/respawn in that room.
respawn_text - text to echo to room when the mob is reset/respawn in that room.
"""
def at_object_creation(self):
"Called at object creation."
super(Enemy, self).at_object_creation()
self.db.tutorial_info = "This moving object will attack players in the same room."
# state machine modes
# state machine modes
self.db.roam_mode = True
self.db.battle_mode = False
self.db.pursue_mode = False
self.db.pursue_mode = False
self.db.dead_mode = False
# health (change this at creation time)
self.db.full_health = 20
@ -159,8 +159,8 @@ class Enemy(Mob):
self.db.dead_at = time.time()
self.db.dead_timer = 100 # how long to stay dead
self.db.inactive = True # this is used during creation to make sure the mob doesn't move away
# store the last player to hit
self.db.last_attacker = None
# store the last player to hit
self.db.last_attacker = None
# where to take defeated enemies
self.db.defeat_location = "darkcell"
self.scripts.add(AttackTimer)
@ -169,26 +169,26 @@ class Enemy(Mob):
"the irregular event is inherited from Mob class"
strings = self.db.irregular_echoes
if strings:
self.location.msg_contents(strings[random.randint(0, len(strings) - 1)])
self.location.msg_contents(strings[random.randint(0, len(strings) - 1)])
def roam(self):
"Called by Attack timer. Will move randomly as long as exits are open."
# in this mode, the mob is healed.
# in this mode, the mob is healed.
self.db.health = self.db.full_health
players = [obj for obj in self.location.contents
players = [obj for obj in self.location.contents
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
if players:
# we found players in the room. Attack.
self.db.roam_mode = False
if players:
# we found players in the room. Attack.
self.db.roam_mode = False
self.db.pursue_mode = False
self.db.battle_mode = True
self.db.battle_mode = True
elif random.random() < 0.2:
# no players to attack, move about randomly.
exits = [ex.destination for ex in self.location.exits if ex.access(self, "traverse")]
if exits:
# Try to make it so the mob doesn't backtrack.
if exits:
# Try to make it so the mob doesn't backtrack.
new_exits = [ex for ex in exits if ex.destination != self.db.last_location]
if new_exits:
exits = new_exits
@ -198,7 +198,7 @@ class Enemy(Mob):
else:
# no exits - a dead end room. Respawn back to start.
self.move_to(self.home)
def attack(self):
"""
This is the main mode of combat. It will try to hit players in
@ -206,11 +206,11 @@ class Enemy(Mob):
to the defeat location.
"""
last_attacker = self.db.last_attacker
players = [obj for obj in self.location.contents
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
players = [obj for obj in self.location.contents
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
if players:
# find a target
# find a target
if last_attacker in players:
# prefer to attack the player last attacking.
target = last_attacker
@ -226,7 +226,7 @@ class Enemy(Mob):
# analyze result.
if target.db.health <= 0:
# we reduced enemy to 0 health. Whisp them off to the prison room.
tloc = search_object(self.db.defeat_location, global_search=True)
tloc = search_object(self.db.defeat_location)
tstring = self.db.defeat_text
if not tstring:
tstring = "You feel your conciousness slip away ... you fall to the ground as "
@ -240,24 +240,24 @@ class Enemy(Mob):
target.location = tloc[0]
tloc[0].at_object_receive(target, self.location)
elif not ostring:
ostring = "%s falls to the ground!" % target.key
ostring = "%s falls to the ground!" % target.key
self.location.msg_contents(ostring, exclude=[target])
else:
# no players found, this could mean they have fled. Switch to pursue mode.
self.battle_mode = False
self.roam_mode = False
self.pursue_mode = True
def pursue(self):
"""
In pursue mode, the enemy tries to find players in adjoining rooms, preferably
those that previously attacked it.
those that previously attacked it.
"""
last_attacker = self.db.last_attacker
players = [obj for obj in self.location.contents if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
players = [obj for obj in self.location.contents if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
if players:
# we found players in the room. Maybe we caught up with some, or some walked in on us
# before we had time to pursue them. Switch to battle mode.
# before we had time to pursue them. Switch to battle mode.
self.battle_mode = True
self.roam_mode = False
self.pursue_mode = False
@ -266,43 +266,43 @@ class Enemy(Mob):
destinations = [ex.destination for ex in self.location.exits if ex.access(self, "traverse")]
# find all players in the possible destinations. OBS-we cannot just use the player's
# current position to move the Enemy; this might have changed when the move is performed,
# causing the enemy to teleport out of bounds.
# causing the enemy to teleport out of bounds.
players = {}
for dest in destinations:
for obj in [o for o in dest.contents if utils.inherits_from(o, BASE_CHARACTER_TYPECLASS)]:
players[obj] = dest
players[obj] = dest
if players:
# we found targets. Move to intercept.
if last_attacker in players:
# preferably the one that last attacked us
self.move_to(players[last_attacker])
else:
# otherwise randomly.
# otherwise randomly.
key = players.keys()[random.randint(0, len(players) - 1)]
self.move_to(players[key])
else:
# we found no players nearby. Return to roam mode.
# we found no players nearby. Return to roam mode.
self.battle_mode = False
self.roam_mode = True
self.pursue_mode = False
def at_hit(self, weapon, attacker, damage):
"""
Called when this object is hit by an enemy's weapon
Should return True if enemy is defeated, False otherwise.
In the case of players attacking, we handle all the events
and information from here, so the return value is not used.
and information from here, so the return value is not used.
"""
self.db.last_attacker = attacker
self.db.last_attacker = attacker
if not self.db.battle_mode:
# we were attacked, so switch to battle mode.
self.db.roam_mode = False
self.db.pursue_mode = False
self.db.battle_mode = True
self.db.pursue_mode = False
self.db.battle_mode = True
#self.scripts.add(AttackTimer)
if not weapon.db.magic:
# In the tutorial, the enemy is a ghostly apparition, so
# only magical weapons can harm it.
@ -310,7 +310,7 @@ class Enemy(Mob):
if not string:
string = "Your weapon just passes through your enemy, causing no effect!"
attacker.msg(string)
return
return
else:
# an actual hit
health = float(self.db.health)
@ -319,10 +319,10 @@ class Enemy(Mob):
if health <= 0:
string = self.db.win_text
if not string:
string = "After your last hit, %s folds in on itself, it seems to fade away into nothingness. " % self.key
string = "After your last hit, %s folds in on itself, it seems to fade away into nothingness. " % self.key
string += "In a moment there is nothing left but the echoes of its screams. But you have a "
string += "feeling it is only temporarily weakened. "
string += "You fear it's only a matter of time before it materializes somewhere again."
string += "You fear it's only a matter of time before it materializes somewhere again."
attacker.msg(string)
string = self.db.win_text_room
if not string:
@ -331,28 +331,28 @@ class Enemy(Mob):
string += "feeling it is only temporarily weakened. "
string += "You fear it's only a matter of time before it materializes somewhere again."
self.location.msg_contents(string, exclude=[attacker])
# put enemy in dead mode and hide it from view. IrregularEvent will bring it back later.
# put enemy in dead mode and hide it from view. IrregularEvent will bring it back later.
self.db.roam_mode = False
self.db.pursue_mode = False
self.db.battle_mode = False
self.db.dead_mode = True
self.db.pursue_mode = False
self.db.battle_mode = False
self.db.dead_mode = True
self.db.dead_at = time.time()
self.location = None
self.location = None
else:
self.location.msg_contents("%s wails, shudders and writhes." % self.key)
return False
return False
def reset(self):
"If the mob was 'dead', respawn it to its home position and reset all modes and damage."
if self.db.dead_mode:
self.db.health = self.db.full_health
self.db.roam_mode = True
self.db.pursue_mode = False
self.db.battle_mode = False
self.db.dead_mode = False
self.location = self.home
self.db.pursue_mode = False
self.db.battle_mode = False
self.db.dead_mode = False
self.location = self.home
string = self.db.respawn_text
if not string:
if not string:
string = "%s fades into existence from out of thin air. It's looking pissed." % self.key
self.location.msg_contents(string)