1 # Plugin for the Ruby IRC bot (http://linuxbrit.co.uk/rbot/)
5 # (c) 2006 Mark Kretschmann <markey@web.de>
6 # Licensed under GPL V2.
9 load '/home/eean/.rbot/plugins/rpg_creatures.rb'
13 attr_accessor :map, :legend
16 @legend = { 'O' => Orc, 'S' => Slime, 's' => Sword }
39 @map = str.split( "\n")
58 def find_by_name( name )
75 attr_accessor :channel, :objects, :map, :party_pos
77 def initialize( channel, bot )
80 @objects = Objects.new
81 @party_pos = Position.new
87 # Read the map and spawn objects
89 m[y].length.times { |x|
95 @party_pos.x, @party_pos.y = x, y
98 o = spawn( @map.legend[c] )
99 o.pos.x, o.pos.y = x, y
107 def set_players_pos( x, y )
108 debug( "set_players_pos(): #{x} #{y}" )
109 @objects.each { |c| c.pos.x, c.pos.y = x, y if c.instance_of?( Player ) }
113 def spawn( klass, name = nil )
125 @bot.say( @channel, text )
131 class RpgPlugin < Plugin
140 def help( plugin, topic="" )
141 "IRC RPG. Commands: 'rpg', 'attack <target>', 'look [object]', 'take <object>', 'inventory', 'stats', 'go <north|n|east|e|south|s|west|w>'."
144 #####################################################################
146 #####################################################################
148 # Returns new Game instance for channel, or existing one
153 unless @games.has_key?( channel )
154 @games[channel] = Game.new( channel, @bot )
157 return @games[channel]
163 g.objects.each do |p|
164 next unless p.kind_of?( Creature )
166 g.say( "#{p.name} dies from his injuries." )
167 g.objects.delete( p )
172 g.objects.each do |p|
173 if p.is_a?( Monster )
180 def spawned?( g, nick )
181 if g.objects.find_by_name( nick )
184 g.say( "You have not joined the game. Use 'rpg' to join." )
190 def target_spawned?( g, target )
191 if g.objects.find_by_name( target )
194 g.say( "There is noone named #{target} near.." )
200 # Returns an array of objects at the same coordinates as p
201 def objects_near( g, p )
203 g.objects.each { |o| objects << o if (o.pos == p.pos and o != p) }
207 #####################################################################
209 #####################################################################
211 def handle_rpg( m, params )
214 o = g.spawn( Player, m.sourcenick )
215 o.pos.x, o.pos.y = g.party_pos.x, g.party_pos.y
216 m.reply "Player #{o.name} enters the game."
220 def handle_spawn_monster( m, params )
223 o = g.spawn( Monster.monsters[rand( Monster.monsters.length )] )
224 o.pos.x, o.pos.y = g.party_pos.x, g.party_pos.y
225 m.reply "A #{o.object_type} enters the game. ('#{o.name}')"
229 def handle_attack( m, params )
231 return unless spawned?( g, m.sourcenick )
232 return unless target_spawned?( g, params[:target] )
234 g.objects[m.sourcenick].attack( g, g.objects[params[:target]] )
239 def handle_look( m, params )
241 return unless spawned?( g, m.sourcenick )
243 p = g.objects.find_by_name( m.sourcenick )
244 x, y = p.pos.x, p.pos.y
245 near = objects_near( g, p )
247 if params[:object] == nil
249 m.reply( "#{m.sourcenick}: You are alone." )
252 near.each { |o| names << o.object_type }
253 m.reply( "#{m.sourcenick}: You see the following objects: #{names.join( ', ' )}." )
256 debug "MAP_LENGTH: #{g.map.map.length}"
257 debug "PARTY_POS: x:#{g.party_pos.x} y:#{g.party_pos.y}"
258 debug "PLAYER_POS: x:#{x} y:#{y}"
259 debug "MAP NORTH: #{g.map.at( x, y-1 )}"
261 north = g.map.wall?( x, y-1 ) ? "a wall" : "open space"
262 east = g.map.wall?( x+1, y ) ? "a wall" : "open space"
263 south = g.map.wall?( x, y+1 ) ? "a wall" : "open space"
264 west = g.map.wall?( x-1, y ) ? "a wall" : "open space"
266 m.reply( "In the north is #{north}, east is #{east}, south is #{south}, and in the west you see #{west}." )
270 if foo.object_type.downcase == params[:object].downcase
276 m.reply( "#{m.sourcenick}: #{p.description}" )
278 m.reply( "#{m.sourcenick}: There is no #{params[:object]} here." )
284 def handle_go( m, params )
286 return unless spawned?( g, m.sourcenick )
288 wall = "Ouch! You bump into a wall."
289 x, y = g.party_pos.x, g.party_pos.y
291 case params[:direction]
293 if g.map.wall?( x, y-1 )
297 str = "You walk northward."
300 if g.map.wall?( x+1, y )
304 str = "You walk eastward."
307 if g.map.wall?( x, y+1 )
311 str = "You walk southward."
314 if g.map.wall?( x-1, y )
318 str = "You walk westward."
321 m.reply( "Go where? Directions: north, east, south, west." )
325 x, y = g.party_pos.x, g.party_pos.y
326 g.set_players_pos( x, y )
329 exits << "north" unless g.map.wall?( x, y-1 )
330 exits << "east" unless g.map.wall?( x+1, y )
331 exits << "south" unless g.map.wall?( x, y+1 )
332 exits << "west" unless g.map.wall?( x-1, y )
333 str += " (Exits: #{exits.join(', ')})"
336 p = g.objects.find_by_name m.sourcenick
337 near = objects_near( g, p )
341 m.reply "You encounter a #{o.object_type}!"
347 def handle_stats( m, params )
349 return unless spawned?( g, m.sourcenick )
351 p = g.objects[m.sourcenick]
352 m.reply( "Stats for #{m.sourcenick}: HP:#{p.hp} XP:#{p.xp} THAC0:#{p.thac0} AC:#{p.ac} HD:#{p.hd}" )
356 def handle_take( m, params )
358 return unless spawned?( g, m.sourcenick )
360 p = g.objects.find_by_name m.sourcenick
361 near = objects_near( g, p )
365 if foo.object_type.downcase == params[:object].downcase
372 m.reply "#{m.sourcenick}: There is no #{params[:object]} here."
376 if t.kind_of?( Creature )
377 m.reply "#{m.sourcenick}: Feeling lonely, eh? You can't take persons."
381 t.pos.x, t.pos.y = nil, nil
383 m.reply "#{m.sourcenick} picks up a #{t.object_type}."
387 def handle_inventory( m, params )
389 return unless spawned?( g, m.sourcenick )
390 p = g.objects.find_by_name m.sourcenick
392 if p.inventory.empty?
393 m.reply "#{m.sourcenick}: You don't carry any objects."
396 p.inventory.each { |i| stuff << i.object_type }
397 m.reply "#{m.sourcenick}: You carry: #{stuff.join(' ')}"
404 plugin = RpgPlugin.new
405 plugin.register( "rpg" )
407 plugin.map 'rpg', :action => 'handle_rpg'
408 plugin.map 'spawn monster', :action => 'handle_spawn_monster'
409 plugin.map 'attack :target', :action => 'handle_attack'
410 plugin.map 'look :object', :action => 'handle_look', :defaults => { :object => nil }
411 plugin.map 'go :direction', :action => 'handle_go'
412 plugin.map 'take :object', :action => 'handle_take'
413 plugin.map 'stats', :action => 'handle_stats'
414 plugin.map 'inventory', :action => 'handle_inventory'