Changeset 188
- Timestamp:
- 11/18/04 14:13:19 (4 years ago)
- Location:
- branches/simplest-thing
- Files:
-
- 1 added
- 8 modified
-
acceptance/epic4.rb (added)
-
lib/fm/entity.rb (modified) (3 diffs)
-
lib/fm/events/perceptual.rb (modified) (5 diffs)
-
lib/fm/gameobject.rb (modified) (1 diff)
-
lib/fm/locus.rb (modified) (5 diffs)
-
lib/fm/mixins.rb (modified) (2 diffs)
-
lib/fm/verb.rb (modified) (3 diffs)
-
test.rb (modified) (1 diff)
-
tests/event.tests.rb (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/simplest-thing/lib/fm/entity.rb
r179 r188 51 51 class FaerieMUD::Entity < FaerieMUD::GameObject 52 52 include FaerieMUD::Hookable, 53 FaerieMUD::Debuggable 53 FaerieMUD::Debuggable, 54 FaerieMUD::ArgCheckFunctions 54 55 55 56 # SVN Revision … … 97 98 ### a FaerieMUD::UnhandledEventError is raised. 98 99 def handleEvents( *events ) 100 checkEachType( events, FaerieMUD::Event ) 99 101 results = [] 100 102 … … 111 113 ### Get a handler as a callable object for the given +event+. 112 114 def getHandlerForEvent( event ) 115 checkType( event, FaerieMUD::Event ) 113 116 handler = @eventHandlerCache[event.class] 114 117 -
branches/simplest-thing/lib/fm/events/perceptual.rb
r172 r188 30 30 module FaerieMUD 31 31 32 ################################################################# 33 ### B A S E P E R C E P T U A L E V E N T T Y P E S 34 ################################################################# 35 32 36 ### The abstract base class for all events which interact with 33 37 ### FaerieMUD::Perception objects. 34 38 class PerceptionEvent < FaerieMUD::Event 35 36 # SVN Revision37 SVNRev = %q$Rev$38 39 # SVN Id40 SVNId = %q$Id$41 42 # SVN URL43 SVNURL = %q$URL$44 45 @properties = [ ]46 47 39 end # class PerceptionEvent 48 40 … … 50 42 ### The class for events which represent visual (sight) information. 51 43 class VisualEvent < FaerieMUD::PerceptionEvent 52 53 # SVN Revision54 SVNRev = %q$Rev$55 56 # SVN Id57 SVNId = %q$Id$58 59 # SVN URL60 SVNURL = %q$URL$61 62 44 end # class VisualPerceptionEvent 63 45 … … 65 47 ### The class of events which represent olfactory (smell) information. 66 48 class OlfactoryEvent < FaerieMUD::PerceptionEvent 67 68 # SVN Revision69 SVNRev = %q$Rev$70 71 # SVN Id72 SVNId = %q$Id$73 74 # SVN URL75 SVNURL = %q$URL$76 77 49 end 78 50 … … 80 52 ### The class of events which represents auditory (heard) information. 81 53 class AuditoryEvent < FaerieMUD::PerceptionEvent 82 83 # SVN Revision84 SVNRev = %q$Rev$85 86 # SVN Id87 SVNId = %q$Id$88 89 # SVN URL90 SVNURL = %q$URL$91 92 54 end 93 55 … … 95 57 ### The class of events which represent tactile (felt) information. 96 58 class TactileEvent < FaerieMUD::PerceptionEvent 59 end 97 60 98 # SVN Revision99 SVNRev = %q$Rev$100 61 101 # SVN Id102 SVNId = %q$Id$103 62 104 # SVN URL 105 SVNURL = %q$URL$ 63 ################################################################# 64 ### S P E C I A L I Z E D E V E N T T Y P E S 65 ################################################################# 106 66 67 # :TODO: Interesting problem: some advanced FaerieMUD languages are composed 68 # of two or more perceptual events together. How to confer that context to 69 # the observer? I suspect the events won't be delivered any differently, but 70 # interpreters for such languages will be heavily context-driven... 71 72 ### The class for events which represent spoken language 73 class SpeechEvent < FaerieMUD::AuditoryEvent 74 75 ### Create a new SpeechEvent 76 def initialize( args={} ) 77 checkForHashArgs( args, :instigator, :language, :words ) 78 super 79 end 80 81 82 ###### 83 public 84 ###### 85 86 # The words that were spoken 87 attr_accessor :words 88 89 # The language the words were spoken in 90 attr_accessor :language 91 92 # The speaker 93 alias_method :speaker, :instigator 94 95 96 ### Return the event as an english sentence. 97 def to_s 98 prelude = super 99 return %q{%s, "%s"} % [ prelude, @words ] 100 end 107 101 end 102 108 103 109 104 -
branches/simplest-thing/lib/fm/gameobject.rb
r172 r188 30 30 ### An abstract base class for all objects in the FaerieMUD game world. 31 31 class FaerieMUD::GameObject 32 include FaerieMUD::Propertied, FaerieMUD::Loggable 32 include FaerieMUD::Propertied, 33 FaerieMUD::Loggable, 34 FaerieMUD::Debuggable, 35 FaerieMUD::ArgCheckFunctions 33 36 34 37 ### Class constants -
branches/simplest-thing/lib/fm/locus.rb
r172 r188 98 98 # 99 99 100 require 'sync' 101 100 102 require 'fm/entity' 101 103 require 'fm/mixins' … … 164 166 165 167 return objects 168 end 169 170 171 ### Append operator -- add the specified ojbect to the contents of the 172 ### receiver and return the receiver. 173 def <<( object ) 174 self.addContents( object ) 175 return self 166 176 end 167 177 … … 235 245 ### The fallback handler for Loci just immerses any events it receives. 236 246 def handleAnyEvent( event ) 247 checkType( event, FaerieMUD::Event ) 237 248 self.log.debug( "Fallback handler: Immersing a #{event.class.name}" ) 238 249 self.immerseEvents( event ) … … 243 254 ### container/s). 244 255 def disperseEvents( *events ) 256 checkEachType( events, FaerieMUD::Event ) 245 257 results = [] 246 258 … … 265 277 ### contents). 266 278 def immerseEvents( *events ) 279 checkEachType( events, FaerieMUD::Event ) 267 280 results = [] 268 281 -
branches/simplest-thing/lib/fm/mixins.rb
r172 r188 56 56 57 57 module FaerieMUD 58 59 ### Mixin that adds some type-checking functions to the current scope 60 module ArgCheckFunctions 61 62 ############### 63 module_function 64 ############### 65 66 ### Check <tt>anObject</tt> to make sure it's one of the specified 67 ### <tt>validTypes</tt>. If the object is not one of the specified value 68 ### types, and an optional block is given it is called with the object being 69 ### tested and the array of valid types. If no handler block is given, a 70 ### <tt>TypeError</tt> is raised. 71 def checkType( anObject, *validTypes ) # :yields: object, *validTypes 72 validTypes.flatten! 73 validTypes.compact! 74 75 unless validTypes.empty? 76 77 ### Compare the object against the array of valid types, and either 78 ### yield to the error block if given or generate our own exception 79 ### if not. 80 unless validTypes.find {|type| anObject.kind_of?( type ) } then 81 typeList = validTypes.collect {|type| type.name}.join(" or ") 82 83 if block_given? then 84 yield( anObject, [ *validTypes ].flatten ) 85 else 86 raise TypeError, 87 "Argument must be of type #{typeList}, not a #{anObject.class.name}", 88 caller(1).find_all {|frame| !frame.include?(__FILE__)} 89 end 90 end 91 else 92 if anObject.nil? then 93 if block_given? then 94 yield( anObject, *validTypes ) 95 else 96 raise ArgumentError, 97 "Argument missing.", 98 caller(1).find_all {|frame| !frame.include?(__FILE__)} 99 end 100 end 101 end 102 103 return true 104 end 105 106 ### Check each object in the specified <tt>objectArray</tt> with a call 107 ### to #checkType with the specified validTypes array. 108 def checkEachType( objectArray, *validTypes, &errBlock ) # :yields: object, *validTypes 109 raise ScriptError, 110 "First argument must be Enumerable" unless 111 objectArray.is_a?( Enumerable ) 112 113 objectArray.each do |anObject| 114 if block_given? then 115 checkType anObject, validTypes, &errBlock 116 else 117 checkType( anObject, *validTypes ) {|obj, vTypes| 118 typeList = vTypes.collect {|type| type.name}.join(" or ") 119 emsg = "Argument must be of type %p, not a %s" % 120 [ typeList, obj.class.name ] 121 trace = caller(1). 122 find_all {|frame| !frame.include?(__FILE__)} 123 raise TypeError, emsg, trace 124 } 125 end 126 end 127 128 return true 129 end 130 131 132 ### Check <tt>anObject</tt> for implementations of <tt>requiredMethods</tt>. 133 ### If one of the methods is unimplemented, and an optional block is given it 134 ### is called with the method that failed the responds_to? test and the object 135 ### being checked. If no handler block is given, a <tt>TypeError</tt> is 136 ### raised. 137 def checkResponse( anObject, *requiredMethods ) # yields method, anObject 138 requiredMethods.flatten! 139 requiredMethods.compact! 140 141 if requiredMethods.size > 0 then 142 requiredMethods.each do |method| 143 next if anObject.respond_to?( method ) 144 145 if block_given? then 146 yield( method, anObject ) 147 else 148 raise TypeError, "Argument '#{anObject.inspect}' does "\ 149 "not answer the '#{method}()' method", 150 caller(1).find_all {|frame| frame.include?(__FILE__)} 151 end 152 end 153 end 154 155 return true 156 end 157 158 159 ### Check each object of <tt>anArray</tt> for implementations of 160 ### <tt>requiredMethods</tt>, calling the optional <tt>errBlock</tt> if 161 ### specified, or raising a <tt>TypeError</tt> if one of the methods is 162 ### unimplemented. 163 def checkEachResponse( anArray, *requiredMethods, &errBlock ) # :yeilds: method, object 164 raise ScriptError, 165 "First argument must be Enumerable" unless 166 anArray.is_a?( Enumerable ) 167 168 anArray.each do |anObject| 169 if block_given? then 170 checkResponse anObject, *requiredMethods, &errBlock 171 else 172 checkResponse( anObject, *requiredMethods ) {|method, object| 173 raise TypeError, "Argument '#{anObject.inspect}' does "\ 174 "not answer the '#{method}()' method", 175 caller(1).find_all {|frame| frame.include?(__FILE__)} 176 } 177 end 178 end 179 180 return true 181 end 182 183 end # module TypeCheckFunctions 184 58 185 59 186 ### A mixin that adds logging to its including class. … … 847 974 func.call( :class => "hash" ) { items } 848 975 end 849 end 976 end # module HTML 850 977 851 978 end # module FaerieMUD -
branches/simplest-thing/lib/fm/verb.rb
r181 r188 21 21 # 22 22 23 require 'singleton' 24 23 25 require 'fm/mixins' 24 26 require 'fm/exceptions' … … 28 30 ### Game verb class 29 31 class FaerieMUD::Verb < FaerieMUD::GameObject 32 include Singleton 30 33 31 34 # SVN Revision … … 44 47 45 48 ### Event interface: "run" the verb, generating the event/s necessary to 46 ### express the action in the game world. The given +instigator+ and47 ### +origin+ will be used when building event/s. See FaerieMUD::Event::new48 ### for definitions49 def happen( instigator, origin )49 ### express the action in the game world. The given +instigator+, +origin+, 50 ### and +target+ will be used when building event/s. See 51 ### FaerieMUD::Event::new for definitions 52 def happen( instigator, origin, target=nil ) 50 53 raise NotImplementedError, 51 54 "Required method #happen not implemented in %s" % 52 55 [self.class.name] 53 56 end 54 55 57 56 58 end # class FaerieMUD::Verb -
branches/simplest-thing/test.rb
r172 r188 50 50 FaerieMUD::Logger::global.outputters << 51 51 FaerieMUD::Logger::Outputter::create( 'file', $stderr, "STDERR" ) 52 Arrow::Logger::global.level = :debug52 FaerieMUD::Logger::global.level = :debug 53 53 $DEBUG = true 54 54 debugMsg "Turned debugging on globally." -
branches/simplest-thing/tests/event.tests.rb
r180 r188 43 43 include Complex 44 44 end 45 45 46 46 47 47 # Set up instances of associated classes for testing … … 56 56 def teardown 57 57 super 58 @entity = @locus = nil58 @entity = @locus = @verb = nil 59 59 end 60 60 … … 67 67 ### Instance test 68 68 def test_00_Instance 69 printTestHeader "Event: Instantiation" 69 70 rval = derivClass = derivObject = nil 70 71 … … 115 116 ### Test the generation of applicable handler names 116 117 def test_10_HandlerNames 118 printTestHeader "Event: Handler names" 117 119 rval = ev = nil 118 120
