[Solution] Lisp Game #49

Discussion in 'Ruby' started by Sean O'Halpin, Oct 6, 2005.

  1. I wasn't going to finish this but somehow I couldn't stop myself.... :)

    It's not tested & debugged but I had to post it before I spent way too
    much time on it.

    Now if I can integrate it with IFMapper...

    ---- CODE ---

    #$DEBUG_GAME =3D true
    def dbg(*args)
    puts *args if $DEBUG_GAME
    end

    class Object
    def in?(container)
    container.include?(self)
    end
    end

    module Attributes
    def has(*names)
    self.class_eval {
    names.each do |name|
    # with args =3D setter
    # without =3D getter
    define_method(name) {|*args|
    if args.size > 0
    instance_variable_set("@#{name}", *args)
    else
    instance_variable_get("@#{name}")
    end
    }
    # also define traditional setter=3D
    define_method("#{name}=3D") {|*args|
    instance_variable_set("@#{name}", *args)
    }
    end
    }
    end

    end

    module Directions
    def directions(*directions)
    directions.each do |name|
    self.class.class_eval {
    define_method(name) {
    go(name)
    }
    }
    end
    end
    end

    class GameObject
    extend Attributes
    has :identifier, :name, :description
    def initialize(identifier, &block)
    @identifier =3D identifier
    instance_eval &block
    end
    end

    class Thing < GameObject
    has :location, :portable

    def initialize(identifier, &block)
    # put defaults before super - they will be overridden in block (if at a=
    ll)
    # e.g. light, dark, etc.
    @portable =3D true
    super
    end

    end

    class Room < GameObject
    has :exits
    end

    class Game
    include Directions

    attr_accessor :name, :rooms, :location, :things

    def initialize(name, &block)
    @name =3D name
    @rooms =3D {}
    @things =3D {}

    # read game definition
    instance_eval &block

    end

    def room(identifier, &block)
    @rooms[symbol(identifier)] =3D Room.new(symbol(identifier), &block)
    end

    def thing(identifier, &block)
    @things[symbol(identifier)] =3D Thing.new(symbol(identifier), &block)
    end

    def match_thing(*identifiers)
    thing =3D nil
    identifiers.each do |identifier|
    if thing =3D @things[identifier]
    break
    end
    end
    thing
    end

    def symbol(s)
    s.to_s.to_sym
    end

    def start(room_identifier)
    @location =3D @rooms[room_identifier]
    end

    def display_list(things)
    if things.size > 2
    things[0..-2].join(", ") + " and " + things[-1]
    else
    things.join(" and ")
    end
    end

    def describe_path(direction, path)
    "a #{path} going #{direction}"
    end

    def describe_exits(location)
    "There is " + display_list(location.exits.map {|direction, (path,
    destination)|
    describe_path(direction, path)
    }) + "."
    end

    def describe_floor(location)
    things =3D @things.select{|key, thing| thing.location =3D=3D location.i=
    dentifier}
    if things.size > 0
    "You can also see " + display_list(things.map{|key, thing| "a
    #{thing.name}"}) + "."
    else
    ""
    end
    end

    def main_loop
    print "> "
    while input =3D gets
    input.chomp!
    case input
    when 'exit', 'quit'
    break
    when 'help'
    puts "Sorry pal! You're on your own here :)"
    else
    begin
    #puts "#{input}"
    tokens =3D input.split
    cmd =3D tokens[0]
    rest =3D tokens[1..-1].map{|x| x.to_sym}.reject{|x| x.in?
    [:the, :to, :eek:n, :in, :a, :with]}
    instance_eval { send(cmd, *rest) }
    rescue Exception =3D> e
    dbg e.to_s
    puts "Eh?"
    end
    end
    print "> "
    end
    end

    # commands taking symbols

    def in_location(location_id, thing_id)
    @things[thing_id].location =3D=3D location_id
    end

    def is_here(thing_id)
    in_location(@location.identifier, thing_id)
    end

    def player_has(thing_id)
    in_location:)player, thing_id)
    end

    def player_in(location_id)
    @location.identifier =3D=3D location_id
    end

    def move_to(location_id, thing_id)
    @things[thing_id].location =3D location_id
    end

    def move_here(thing_id)
    move_to(@location.identifier, thing_id)
    end

    def destroy(thing_id)
    move_to:)nowhere, thing_id)
    end

    def pick_up(thing_id)
    move_to:)player, thing_id)
    end

    # verbs

    def look
    puts location.description
    puts describe_exits(location)
    puts describe_floor(location)
    end

    def go(direction)
    dest =3D @location.exits[direction]
    if dest
    @location =3D @rooms[dest[1]]
    look
    else
    puts "You can't move in that direction"
    end
    end
    alias :walk :go

    def inventory
    carried =3D @things.select{|key, thing| player_has(thing.identifier)}
    puts "You are carrying " +
    if carried.size > 0
    "a #{display_list(carried.map{|key, thing| thing.name})}"
    else
    "nothing"
    end
    end
    alias :i :inventory

    def get(*args)
    if thing =3D match_thing(*args)
    if is_here(thing.identifier)
    if thing.portable
    pick_up(thing.identifier)
    puts "OK - you picked up the #{thing.name}"
    else
    puts "You try and you try but you just can't pick up the
    #{thing.name}"
    end
    else
    puts "You can't see a #{thing.name} here"
    end
    else
    puts "Get what?"
    end
    end
    alias :take :get

    def drop(*args)
    if thing =3D match_thing(*args)
    if player_has(thing.identifier)
    move_here(thing.identifier)
    puts "OK - you dropped the #{thing.name}"
    else
    "You're not carrying a #{thing.name}"
    end
    else
    puts "Drop what?"
    end
    end

    def examine(*args)
    if obj =3D match_thing(*args)
    if is_here(obj.identifier)
    puts "Looks like #{obj.description}"
    else
    puts "You can't see that here"
    end
    else
    puts "Don't know what you're talking about"
    end
    end
    alias :exam :examine

    end

    def game(name, &block)
    puts "Welcome to #{name}\n\n"
    g =3D Game.new(name, &block)
    g.look
    g.main_loop
    end

    # Game definition

    game "Ruby Adventure" do

    directions :east, :west, :north, :south, :upstairs, :downstairs
    alias :up :upstairs
    alias :down :downstairs

    # rooms

    room :living_room do
    name 'Living Room'
    description "You are in the living-room of a wizard's house. There
    is a wizard snoring loudly on the couch."
    exits :west =3D> [:door, :garden],
    :upstairs =3D> [:stairway, :attic]
    end

    room :garden do
    name 'Garden'
    description "You are in a beautiful garden. There is a well in
    front of you."
    exits :east =3D> [:door, :living_room]
    end

    room :attic do
    name "Attic"
    description "You are in the attic of the wizard's house. There is
    a giant welding torch in the corner."
    exits :downstairs =3D> [:stairway, :living_room]
    end

    start :living_room

    # things

    thing :wizard do
    name "wizard"
    description "a typical wizard - pointy hat, wand, unkempt beard,
    smelly feet"
    location :living_room
    portable false
    end

    thing :self do
    name "Yourself"
    description "your same ol' ugly self"
    portable false
    end

    thing :bottle do
    name 'whiskey bottle'
    description 'a half-empty whiskey bottle'
    location :living_room
    end

    thing :bucket do
    name 'bucket'
    description 'a rusty bucket'
    location :living_room
    end

    thing :welded_bucket do
    name "bucket"
    description "a bucket with a chain welded to it"
    location :nowhere
    end

    thing :filled_bucket do
    name "bucket"
    description "a bucket full of water with a chain welded to it"
    location :nowhere
    end

    # chain
    thing :chain do
    name 'chain'
    description 'a sturdy iron chain'
    location :garden
    end

    thing :frog do
    name 'frog'
    description 'a wide-mouthed frog'
    location :garden
    end

    # verbs

    def splash(*args)
    thing, *rest =3D *args
    if thing =3D=3D :wizard and player_in:)living_room) and
    player_has:)filled_bucket)
    if player_has:)frog)
    puts "The wizard awakens and sees that you stole his frog. He
    is so upset he banishes you to the netherworlds - you lose! The end."
    break
    else
    puts "The wizard awakens from his slumber and greets you
    warmly. He hands you the magic low-carb donut - you win! The end."
    break
    end
    elsif thing =3D=3D :bucket
    puts "The bucket has nothing in it"
    else
    puts "With what?"
    end
    end

    def attach(*args)
    subject, object, *rest =3D *args
    if [subject, object].in?([[:chain, :bucket], [:bucket, :chain]])
    and player_in:)attic) and player_has:)bucket) and player_has:)chain)
    destroy:)bucket)
    destroy:)chain)
    pick_up:)welded_bucket)
    puts "The chain is now securely welded to the bucket."
    else
    puts "Interesting..."
    end
    end
    alias :weld :attach

    def fill(*args)
    thing, *rest =3D *args
    if thing =3D=3D :bucket and player_in:)garden) and player_has:)welded_b=
    ucket)
    destroy:)welded_bucket)
    pick_up:)filled_bucket)
    puts "You have filled the bucket with water"
    elsif thing =3D=3D :bucket
    if player_in:)garden)
    puts "You can't reach the water in the well. You'll need
    something to lower the bucket down"
    elsif player_has:)bucket)
    puts "Fill it with what?"
    else
    puts "You don't have the bucket!"
    end
    else
    puts "Hmmmm...."
    end
    end
    alias :dunk :fill

    end

    __END__
    get bucket
    go west
    get chain
    east
    upstairs
    weld chain to bucket
    down
    west
    fill bucket
    east
    splash wizard

    --- END CODE ---

    Regards,

    Sean
    Sean O'Halpin, Oct 6, 2005
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ekzept
    Replies:
    0
    Views:
    356
    ekzept
    Aug 10, 2007
  2. Jim Menard

    [SOLUTION] Lisp Game (#49)

    Jim Menard, Oct 2, 2005, in forum: Ruby
    Replies:
    9
    Views:
    97
  3. Markus Koenig

    [SOLUTION] Lisp Game (#49)

    Markus Koenig, Oct 2, 2005, in forum: Ruby
    Replies:
    5
    Views:
    114
    James Edward Gray II
    Oct 9, 2005
  4. Brian Schröder

    [Quiz] [Solution] Lisp Game

    Brian Schröder, Oct 3, 2005, in forum: Ruby
    Replies:
    2
    Views:
    108
    James Edward Gray II
    Oct 5, 2005
  5. Louis J Scoras
    Replies:
    13
    Views:
    305
    Dave Burt
    Oct 5, 2005
Loading...

Share This Page