------------wXkDTjTmcKHHO5WXuKtn0q Content-Type: text/plain; format=flowed; delsp=yes; charset=iso-8859-15 Content-Transfer-Encoding: 8bit This was really a very nice quiz. I actually had bookmarked this tutorial, but this quiz finally motivated me to read it. I did two versions: The first versions is an almost literal translation of the lisp code (see attachment). It uses Hashes instead of Arrays for some stuff and describe_path has a different interface but other than that it's very similar to the original. I also used method_missing to allow the user to write "pickup bucket" instead of "pickup :bucket". The second versions (see below and attachment) is still near the lisp version but object oriented and more ruby-like. And thanks to Brian Schröäer and his thread "Eval and block problems" (and of course to everybody, who replied): I had a bug in my game_action method, I used "block.call" instead of "instance_eval &block". I wouldn't have found this without the thread because it actually worked because of my method_missing trick... Here is a walkthrough (spoiler alert ;-): $ irb --prompt simple -r lispgame.rb >> WizardGame.start_irb_game nil >> help [describe_floor, describe_location, describe_paths, dunk, get, go, h, help, i, inventory, l, look, pickup, pickup_object, splash, take, w, walk, walk_direction, weld] >> l you are in the living-room of a wizard's house. there is a wizard snoring loudly on the couch. there is a door going west from here. there is a stairway going upstairs from here. you see a whiskey_bottle on the floor. you see a bucket on the floor. >> take bucket you are now carrying the bucket >> go west you are in a beautiful garden. there is a well in front of you. there is a door going east from here. you see a frog on the floor. you see a chain on the floor. >> dunk bucket, well the water level is too low to reach. >> pickup chain you are now carrying the chain >> w east you are in the living-room of a wizard's house. there is a wizard snoring loudly on the couch. there is a door going west from here. there is a stairway going upstairs from here. you see a whiskey_bottle on the floor. >> i [bucket, chain] >> w upstairs you are in the attic of the abandoned house. there is a giant welding torch in the corner. there is a stairway going downstairs from here. >> weld chain, bucket the chain is now securely welded to the bucket. >> w downstairs you are in the living-room of a wizard's house. there is a wizard snoring loudly on the couch. there is a door going west from here. there is a stairway going upstairs from here. you see a whiskey_bottle on the floor. >> w west you are in a beautiful garden. there is a well in front of you. there is a door going east from here. you see a frog on the floor. >> dunk bucket, well the bucket is now full of water. >> w east you are in the living-room of a wizard's house. there is a wizard snoring loudly on the couch. there is a door going west from here. there is a stairway going upstairs from here. you see a whiskey_bottle on the floor. >> splash bucket, wizard the wizard awakens from his slumber and greets you warmly. he hands you the magic low-carb donut- you win! the end. Dominik The code of the second version: class TextAdventureEngine Location truct.new(:description, :paths) Path truct.new(:description, :destination) def describe_location @map[@location].description end def describe_paths paths map[@location].paths paths.keys.map { |dir| "there is a #{paths[dir].description} going #{dir} from here." }.join(" ") end def is_at?(object, location) @object_locations[object] location end def describe_floor @objects.find_all { |obj| is_at?(obj, @location) }.map { |obj| "you see a #{obj} on the floor." }.join(" ") end def look [describe_location, describe_paths, describe_floor].join("\n") end alias :l :look def walk_direction(direction) next_loc map[@location].paths[direction] if next_loc @location ext_loc.destination look else "you can't go that way." end end alias :walk :walk_direction alias :go :walk_direction alias :w :walk_direction def pickup_object(object) if is_at?(object, @location) @object_locations[object] body "you are now carrying the #{object}" else "you cannot get that." end end alias :pickup :pickup_object alias :take :pickup_object alias :get :pickup_object def inventory @objects.find_all { |obj| is_at?(obj, :body) }.map { |o| o.to_s } end alias :i :inventory def have?(object) is_at?(object, :body) end def help (methods - Object.instance_methods).reject { |m| m \?$/ }.sort end alias :h :help def self.game_action(command, subj, obj, place, &block) define_method(command) { |subject, object| if @location place && subject subj && object obj && have?(subj) instance_eval &block else "i can't #{command} like that." end } end def self.start_irb_game $irb_ta elf.new Object.class_eval { # send missing methods to $irb_ta or return their name as symbol def method_missing(m, *a, &b) if $irb_ta.respond_to? m $irb_ta.send(m, *a, &b) elsif (a.empty? && !b) m else super end end } String.class_eval { # nicer output def inspect self end } end end class WizardGame < TextAdventureEngine def initialize @objects :whiskey_bottle, :bucket, :frog, :chain] @map :living_room Location.new( "you are in the living-room of a wizard's house. there is a wizard snoring loudly on the couch.", {:west Path.new("door", :garden), :upstairs Path.new("stairway", :attic)} ), :garden Location.new( "you are in a beautiful garden. there is a well in front of you.", {:east Path.new("door", :living_room)} ), :attic Location.new( "you are in the attic of the abandoned house. there is a giant welding torch in the corner.", {:downstairs Path.new("stairway", :living_room)} ) } @object_locations :whiskey_bottle :living_room, :bucket :living_room, :chain :garden, :frog :garden } @location living_room end game_action(:weld, :chain, :bucket, :attic) { if have?(:bucket) @chain_welded rue "the chain is now securely welded to the bucket." else "you do not have a bucket." end } game_action(:dunk, :bucket, :well, :garden) { if @chain_welded @bucket_filled rue "the bucket is now full of water." else "the water level is too low to reach." end } game_action(:splash, :bucket, :wizard, :living_room) { if not @bucket_filled "the bucket has nothing in it." elsif have?(:frog) "the wizard awakens and sees that you stole his frog. he is so upset he banishes you to the netherworlds- you lose! the end." else "the wizard awakens from his slumber and greets you warmly. he hands you the magic low-carb donut- you win! the end." end } end ------------wXkDTjTmcKHHO5WXuKtn0q Content-Disposition: attachment; filename=lispgame.rb Content-Type: application/octet-stream; name=lispgame.rb Content-Transfer-Encoding: Base64 CmNsYXNzIFRleHRBZHZlbnR1cmVFbmdpbmUKCglMb2NhdGlvbiA9IFN0cnVjdC5u ZXcoOmRlc2NyaXB0aW9uLCA6cGF0aHMpCglQYXRoID0gU3RydWN0Lm5ldyg6ZGVz Y3JpcHRpb24sIDpkZXN0aW5hdGlvbikKCglkZWYgZGVzY3JpYmVfbG9jYXRpb24K CQlAbWFwW0Bsb2NhdGlvbl0uZGVzY3JpcHRpb24KCWVuZAoKCWRlZiBkZXNjcmli ZV9wYXRocwoJCXBhdGhzID0gQG1hcFtAbG9jYXRpb25dLnBhdGhzCgkJcGF0aHMu a2V5cy5tYXAgeyB8ZGlyfAoJCQkidGhlcmUgaXMgYSAje3BhdGhzW2Rpcl0uZGVz Y3JpcHRpb259IGdvaW5nICN7ZGlyfSBmcm9tIGhlcmUuIgoJCX0uam9pbigiICIp CgllbmQKCglkZWYgaXNfYXQ/KG9iamVjdCwgbG9jYXRpb24pCgkJQG9iamVjdF9s b2NhdGlvbnNbb2JqZWN0XSA9PSBsb2NhdGlvbgoJZW5kCgoJZGVmIGRlc2NyaWJl X2Zsb29yCgkJQG9iamVjdHMuZmluZF9hbGwgeyB8b2JqfCBpc19hdD8ob2JqLCBA bG9jYXRpb24pIH0ubWFwIHsgfG9ianwKCQkJInlvdSBzZWUgYSAje29ian0gb24g dGhlIGZsb29yLiIKCQl9LmpvaW4oIiAiKQoJZW5kCgoJZGVmIGxvb2sKCQlbZGVz Y3JpYmVfbG9jYXRpb24sIGRlc2NyaWJlX3BhdGhzLCBkZXNjcmliZV9mbG9vcl0u am9pbigiXG4iKQoJZW5kCgoJYWxpYXMgOmwgOmxvb2sKCglkZWYgd2Fsa19kaXJl Y3Rpb24oZGlyZWN0aW9uKQoJCW5leHRfbG9jID0gQG1hcFtAbG9jYXRpb25dLnBh dGhzW2RpcmVjdGlvbl0KCQlpZiBuZXh0X2xvYwoJCQlAbG9jYXRpb24gPSBuZXh0 X2xvYy5kZXN0aW5hdGlvbgoJCQlsb29rCgkJZWxzZQoJCQkieW91IGNhbid0IGdv IHRoYXQgd2F5LiIKCQllbmQKCWVuZAoKCWFsaWFzIDp3YWxrIDp3YWxrX2RpcmVj dGlvbgoJYWxpYXMgOmdvIDp3YWxrX2RpcmVjdGlvbgoJYWxpYXMgOncgOndhbGtf ZGlyZWN0aW9uCgoJZGVmIHBpY2t1cF9vYmplY3Qob2JqZWN0KQoJCWlmIGlzX2F0 PyhvYmplY3QsIEBsb2NhdGlvbikKCQkJQG9iamVjdF9sb2NhdGlvbnNbb2JqZWN0 XSA9IDpib2R5CgkJCSJ5b3UgYXJlIG5vdyBjYXJyeWluZyB0aGUgI3tvYmplY3R9 IgoJCWVsc2UKCQkJInlvdSBjYW5ub3QgZ2V0IHRoYXQuIgoJCWVuZAoJZW5kCgoJ YWxpYXMgOnBpY2t1cCA6cGlja3VwX29iamVjdAoJYWxpYXMgOnRha2UgOnBpY2t1 cF9vYmplY3QKCWFsaWFzIDpnZXQgOnBpY2t1cF9vYmplY3QKCglkZWYgaW52ZW50 b3J5CgkJQG9iamVjdHMuZmluZF9hbGwgeyB8b2JqfAoJCQlpc19hdD8ob2JqLCA6 Ym9keSkKCQl9Lm1hcCB7IHxvfCBvLnRvX3MgfQoJZW5kCgoJYWxpYXMgOmkgOmlu dmVudG9yeQoKCWRlZiBoYXZlPyhvYmplY3QpCgkJaXNfYXQ/KG9iamVjdCwgOmJv ZHkpCgllbmQKCglkZWYgaGVscAoJCShtZXRob2RzIC0gT2JqZWN0Lmluc3RhbmNl X21ldGhvZHMpLnJlamVjdCB7IHxtfCBtPX4vXD8kLyB9LnNvcnQKCWVuZAoKCWFs aWFzIDpoIDpoZWxwCgoJZGVmIHNlbGYuZ2FtZV9hY3Rpb24oY29tbWFuZCwgc3Vi aiwgb2JqLCBwbGFjZSwgJmJsb2NrKQoJCWRlZmluZV9tZXRob2QoY29tbWFuZCkg eyB8c3ViamVjdCwgb2JqZWN0fAoJCQlpZiBAbG9jYXRpb24gPT0gcGxhY2UgJiYg c3ViamVjdCA9PSBzdWJqICYmIG9iamVjdCA9PSBvYmogJiYgaGF2ZT8oc3ViaikK CQkJCWluc3RhbmNlX2V2YWwgJmJsb2NrCgkJCWVsc2UKCQkJCSJpIGNhbid0ICN7 Y29tbWFuZH0gbGlrZSB0aGF0LiIKCQkJZW5kCgkJfQoJZW5kCgoJZGVmIHNlbGYu c3RhcnRfaXJiX2dhbWUKCQkkaXJiX3RhID0gc2VsZi5uZXcKCQlPYmplY3QuY2xh c3NfZXZhbCB7CgkJCSMgc2VuZCBtaXNzaW5nIG1ldGhvZHMgdG8gJGlyYl90YSBv ciByZXR1cm4gdGhlaXIgbmFtZSBhcyBzeW1ib2wKCQkJZGVmIG1ldGhvZF9taXNz aW5nKG0sICphLCAmYikKCQkJCWlmICRpcmJfdGEucmVzcG9uZF90bz8gbQoJCQkJ CSRpcmJfdGEuc2VuZChtLCAqYSwgJmIpCgkJCQllbHNpZiAoYS5lbXB0eT8gJiYg IWIpCgkJCQkJbQoJCQkJZWxzZQoJCQkJCXN1cGVyCgkJCQllbmQKCQkJZW5kCgkJ fQoJCVN0cmluZy5jbGFzc19ldmFsIHsKCQkJIyBuaWNlciBvdXRwdXQKCQkJZGVm IGluc3BlY3QKCQkJCXNlbGYKCQkJZW5kCgkJfQoJZW5kCgplbmQKCgpjbGFzcyBX aXphcmRHYW1lIDwgVGV4dEFkdmVudHVyZUVuZ2luZQoKCWRlZiBpbml0aWFsaXpl CgkJQG9iamVjdHMgPSBbOndoaXNrZXlfYm90dGxlLCA6YnVja2V0LCA6ZnJvZywg OmNoYWluXQoKCQlAbWFwID0gewoJCQk6bGl2aW5nX3Jvb20gPT4gTG9jYXRpb24u bmV3KAoJCQkieW91IGFyZSBpbiB0aGUgbGl2aW5nLXJvb20gb2YgYSB3aXphcmQn cyBob3VzZS4gdGhlcmUgaXMgYSB3aXphcmQgc25vcmluZyBsb3VkbHkgb24gdGhl IGNvdWNoLiIsCgkJCXs6d2VzdCA9PiBQYXRoLm5ldygiZG9vciIsIDpnYXJkZW4p LCA6dXBzdGFpcnMgPT4gUGF0aC5uZXcoInN0YWlyd2F5IiwgOmF0dGljKX0KCQkJ KSwKCQkJOmdhcmRlbiA9PiBMb2NhdGlvbi5uZXcoCgkJCSJ5b3UgYXJlIGluIGEg YmVhdXRpZnVsIGdhcmRlbi4gdGhlcmUgaXMgYSB3ZWxsIGluIGZyb250IG9mIHlv dS4iLAoJCQl7OmVhc3QgPT4gUGF0aC5uZXcoImRvb3IiLCA6bGl2aW5nX3Jvb20p fQoJCQkpLAoJCQk6YXR0aWMgPT4gTG9jYXRpb24ubmV3KAoJCQkieW91IGFyZSBp biB0aGUgYXR0aWMgb2YgdGhlIGFiYW5kb25lZCBob3VzZS4gdGhlcmUgaXMgYSBn aWFudCB3ZWxkaW5nIHRvcmNoIGluIHRoZSBjb3JuZXIuIiwKCQkJezpkb3duc3Rh aXJzID0+IFBhdGgubmV3KCJzdGFpcndheSIsIDpsaXZpbmdfcm9vbSl9CgkJCSkK CQl9CgoJCUBvYmplY3RfbG9jYXRpb25zID0gewoJCQk6d2hpc2tleV9ib3R0bGUg PT4gOmxpdmluZ19yb29tLAoJCQk6YnVja2V0ID0+IDpsaXZpbmdfcm9vbSwKCQkJ OmNoYWluID0+IDpnYXJkZW4sCgkJCTpmcm9nID0+IDpnYXJkZW4KCQl9CgoJCUBs b2NhdGlvbiA9IDpsaXZpbmdfcm9vbQoJZW5kCgoJZ2FtZV9hY3Rpb24oOndlbGQs IDpjaGFpbiwgOmJ1Y2tldCwgOmF0dGljKSB7CgkJaWYgaGF2ZT8oOmJ1Y2tldCkK CQkJQGNoYWluX3dlbGRlZCA9IHRydWUKCQkJInRoZSBjaGFpbiBpcyBub3cgc2Vj dXJlbHkgd2VsZGVkIHRvIHRoZSBidWNrZXQuIgoJCWVsc2UKCQkJInlvdSBkbyBu b3QgaGF2ZSBhIGJ1Y2tldC4iCgkJZW5kCgl9CgoJZ2FtZV9hY3Rpb24oOmR1bmss IDpidWNrZXQsIDp3ZWxsLCA6Z2FyZGVuKSB7CgkJaWYgQGNoYWluX3dlbGRlZAoJ CQlAYnVja2V0X2ZpbGxlZCA9IHRydWUKCQkJInRoZSBidWNrZXQgaXMgbm93IGZ1 bGwgb2Ygd2F0ZXIuIgoJCWVsc2UKCQkJInRoZSB3YXRlciBsZXZlbCBpcyB0b28g bG93IHRvIHJlYWNoLiIKCQllbmQKCX0KCglnYW1lX2FjdGlvbig6c3BsYXNoLCA6 YnVja2V0LCA6d2l6YXJkLCA6bGl2aW5nX3Jvb20pIHsKCQlpZiBub3QgQGJ1Y2tl dF9maWxsZWQKCQkJInRoZSBidWNrZXQgaGFzIG5vdGhpbmcgaW4gaXQuIgoJCWVs c2lmIGhhdmU/KDpmcm9nKQoJCQkidGhlIHdpemFyZCBhd2FrZW5zIGFuZCBzZWVz IHRoYXQgeW91IHN0b2xlIGhpcyBmcm9nLiBoZSBpcyBzbyB1cHNldCBoZSBiYW5p c2hlcyB5b3UgdG8gdGhlIG5ldGhlcndvcmxkcy0geW91IGxvc2UhIHRoZSBlbmQu IgoJCWVsc2UKCQkJInRoZSB3aXphcmQgYXdha2VucyBmcm9tIGhpcyBzbHVtYmVy IGFuZCBncmVldHMgeW91IHdhcm1seS4gaGUgaGFuZHMgeW91IHRoZSBtYWdpYyBs b3ctY2FyYiBkb251dC0geW91IHdpbiEgdGhlIGVuZC4iCgkJZW5kCgl9CgplbmQK ------------wXkDTjTmcKHHO5WXuKtn0q Content-Disposition: attachment; filename=lispgame_literal.rb Content-Type: application/octet-stream; name=lispgame_literal.rb Content-Transfer-Encoding: Base64 CiRvYmplY3RzID0gWzp3aGlza2V5X2JvdHRsZSwgOmJ1Y2tldCwgOmZyb2csIDpj aGFpbl0KCiRtYXAgPSB7Cgk6bGl2aW5nX3Jvb20gPT4gWyJ5b3UgYXJlIGluIHRo ZSBsaXZpbmctcm9vbSBvZiBhIHdpemFyZCdzIGhvdXNlLiB0aGVyZSBpcyBhIHdp emFyZCBzbm9yaW5nIGxvdWRseSBvbiB0aGUgY291Y2guIiwKCQl7Ondlc3QgPT4g WyJkb29yIiwgOmdhcmRlbl0sIDp1cHN0YWlycyA9PiBbInN0YWlyd2F5IiwgOmF0 dGljXX1dLAoJOmdhcmRlbiA9PiBbInlvdSBhcmUgaW4gYSBiZWF1dGlmdWwgZ2Fy ZGVuLiB0aGVyZSBpcyBhIHdlbGwgaW4gZnJvbnQgb2YgeW91LiIsCgkJezplYXN0 ID0+IFsiZG9vciIsIDpsaXZpbmdfcm9vbV19XSwKCTphdHRpYyA9PiBbInlvdSBh cmUgaW4gdGhlIGF0dGljIG9mIHRoZSBhYmFuZG9uZWQgaG91c2UuIHRoZXJlIGlz IGEgZ2lhbnQgd2VsZGluZyB0b3JjaCBpbiB0aGUgY29ybmVyLiIsCgkJezpkb3du c3RhaXJzID0+IFsic3RhaXJ3YXkiLCA6bGl2aW5nX3Jvb21dfV0KfQoKJG9iamVj dF9sb2NhdGlvbnMgPSB7Cgk6d2hpc2tleV9ib3R0bGUgPT4gOmxpdmluZ19yb29t LAoJOmJ1Y2tldCA9PiA6bGl2aW5nX3Jvb20sCgk6Y2hhaW4gPT4gOmdhcmRlbiwK CTpmcm9nID0+IDpnYXJkZW4KfQoKJGxvY2F0aW9uID0gOmxpdmluZ19yb29tCgpk ZWYgZGVzY3JpYmVfbG9jYXRpb24obG9jYXRpb24sIG1hcCkKCW1hcFtsb2NhdGlv bl1bMF0KZW5kCgpkZWYgZGVzY3JpYmVfcGF0aChwYXRocywgZGlyZWN0aW9uKQoJ InRoZXJlIGlzIGEgI3twYXRoc1tkaXJlY3Rpb25dWzBdfSBnb2luZyAje2RpcmVj dGlvbn0gZnJvbSBoZXJlLiIKZW5kCgpkZWYgZGVzY3JpYmVfcGF0aHMobG9jYXRp b24sIG1hcCkKCXBhdGhzID0gbWFwW2xvY2F0aW9uXVsxXQoJcGF0aHMua2V5cy5t YXAgeyB8ZGlyfCBkZXNjcmliZV9wYXRoKHBhdGhzLCBkaXIpIH0uam9pbigiICIp CmVuZAoKZGVmIGlzX2F0KG9iaiwgbG9jLCBvYmpfbG9jKQoJb2JqX2xvY1tvYmpd ID09IGxvYwplbmQKCmRlZiBkZXNjcmliZV9mbG9vcihsb2MsIG9ianMsIG9ial9s b2MpCglvYmpzLmZpbmRfYWxsIHsgfG9ianwgaXNfYXQob2JqLCBsb2MsIG9ial9s b2MpIH0ubWFwIHsgfG9ianwKCQkieW91IHNlZSBhICN7b2JqfSBvbiB0aGUgZmxv b3IuIgoJfS5qb2luKCIgIikKZW5kCgpkZWYgbG9vawoJWwoJZGVzY3JpYmVfbG9j YXRpb24oJGxvY2F0aW9uLCAkbWFwKSwKCWRlc2NyaWJlX3BhdGhzKCRsb2NhdGlv biwgJG1hcCksCglkZXNjcmliZV9mbG9vcigkbG9jYXRpb24sICRvYmplY3RzLCAk b2JqZWN0X2xvY2F0aW9ucykKCV0uam9pbigiICIpCmVuZAoKZGVmIHdhbGtfZGly ZWN0aW9uKGRpcmVjdGlvbikKCW5leHRfbG9jID0gJG1hcFskbG9jYXRpb25dWzFd W2RpcmVjdGlvbl0KCWlmIG5leHRfbG9jCgkJJGxvY2F0aW9uID0gbmV4dF9sb2Nb MV0KCQlsb29rCgllbHNlCgkJInlvdSBjYW4ndCBnbyB0aGF0IHdheS4iCgllbmQK ZW5kCgojIG1hcCBhbGwgbWlzc2luZyBtZXRob2RzIHdpdGhvdXQgYXJndW1lbnRz IHRvIHRoZXJlIG5hbWUgYXMgc3ltYm9sLCBzbyB0aGUKIyBwbGF5ZXIgY2FuIHdy aXRlIGJ1Y2tldCBpbnN0ZWFkIG9mIDpidWNrZXQKZGVmIG1ldGhvZF9taXNzaW5n KG0sICphLCAmYikKCWEuZW1wdHk/ID8gbSA6IHN1cGVyCmVuZAoKYWxpYXMgOndh bGsgOndhbGtfZGlyZWN0aW9uCgpkZWYgcGlja3VwX29iamVjdChvYmplY3QpCglp ZiBpc19hdChvYmplY3QsICRsb2NhdGlvbiwgJG9iamVjdF9sb2NhdGlvbnMpCgkJ JG9iamVjdF9sb2NhdGlvbnNbb2JqZWN0XSA9IDpib2R5CgkJInlvdSBhcmUgbm93 IGNhcnJ5aW5nIHRoZSAje29iamVjdH0iCgllbHNlCgkJInlvdSBjYW5ub3QgZ2V0 IHRoYXQuIgoJZW5kCmVuZAoKYWxpYXMgOnBpY2t1cCA6cGlja3VwX29iamVjdAoK ZGVmIGludmVudG9yeQoJJG9iamVjdHMuZmluZF9hbGwgeyB8b2JqfAoJCWlzX2F0 KG9iaiwgOmJvZHksICRvYmplY3RfbG9jYXRpb25zKQoJfQplbmQKCmRlZiBoYXZl KG9iamVjdCkKCWludmVudG9yeS5pbmNsdWRlPyBvYmplY3QKZW5kCgpkZWYgZ2Ft ZV9hY3Rpb24oY29tbWFuZCwgc3Viaiwgb2JqLCBwbGFjZSwgJmJsb2NrKQoJc2Vs Zi5jbGFzcy5jbGFzc19ldmFsIHsKCQlkZWZpbmVfbWV0aG9kKGNvbW1hbmQpIHsg fHN1YmplY3QsIG9iamVjdHwKCQkJaWYgJGxvY2F0aW9uID09IHBsYWNlICYmIHN1 YmplY3QgPT0gc3ViaiAmJiBvYmplY3QgPT0gb2JqICYmIGhhdmUoc3ViaikKCQkJ CWluc3RhbmNlX2V2YWwgJmJsb2NrCgkJCWVsc2UKCQkJCSJpIGNhbid0ICN7Y29t bWFuZH0gbGlrZSB0aGF0LiIKCQkJZW5kCgkJfQoJfQplbmQKCiRjaGFpbl93ZWxk ZWQgPT0gZmFsc2UKJGJ1Y2tldF9maWxsZWQgPT0gZmFsc2UKCmdhbWVfYWN0aW9u KDp3ZWxkLCA6Y2hhaW4sIDpidWNrZXQsIDphdHRpYykgewoJaWYgaGF2ZSg6YnVj a2V0KSAmJiAoJGNoYWluX3dlbGRlZCA9IHRydWUpCgkJInRoZSBjaGFpbiBpcyBu b3cgc2VjdXJlbHkgd2VsZGVkIHRvIHRoZSBidWNrZXQuIgoJZWxzZQoJCSJ5b3Ug ZG8gbm90IGhhdmUgYSBidWNrZXQuIgoJZW5kCn0KCmdhbWVfYWN0aW9uKDpkdW5r LCA6YnVja2V0LCA6d2VsbCwgOmdhcmRlbikgewoJaWYgJGNoYWluX3dlbGRlZAoJ CSRidWNrZXRfZmlsbGVkID0gdHJ1ZQoJCSJ0aGUgYnVja2V0IGlzIG5vdyBmdWxs IG9mIHdhdGVyLiIKCWVsc2UKCQkidGhlIHdhdGVyIGxldmVsIGlzIHRvbyBsb3cg dG8gcmVhY2guIgoJZW5kCn0KCmdhbWVfYWN0aW9uKDpzcGxhc2gsIDpidWNrZXQs IDp3aXphcmQsIDpsaXZpbmdfcm9vbSkgewoJaWYgISRidWNrZXRfZmlsbGVkCgkJ InRoZSBidWNrZXQgaGFzIG5vdGhpbmcgaW4gaXQuIgoJZWxzaWYgaGF2ZSg6ZnJv ZykKCQkidGhlIHdpemFyZCBhd2FrZW5zIGFuZCBzZWVzIHRoYXQgeW91IHN0b2xl IGhpcyBmcm9nLiBoZSBpcyBzbyB1cHNldCBoZSBiYW5pc2hlcyB5b3UgdG8gdGhl IG5ldGhlcndvcmxkcy0geW91IGxvc2UhIHRoZSBlbmQuIgoJZWxzZQoJCSJ0aGUg d2l6YXJkIGF3YWtlbnMgZnJvbSBoaXMgc2x1bWJlciBhbmQgZ3JlZXRzIHlvdSB3 YXJtbHkuIGhlIGhhbmRzIHlvdSB0aGUgbWFnaWMgbG93LWNhcmIgZG9udXQtIHlv dSB3aW4hIHRoZSBlbmQuIgoJZW5kCn0K ------------wXkDTjTmcKHHO5WXuKtn0q--