Skip to content

Instantly share code, notes, and snippets.

@jaymcgavren
Last active January 23, 2024 06:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaymcgavren/241b1720e57beffc2e5a3afb15581b25 to your computer and use it in GitHub Desktop.
Save jaymcgavren/241b1720e57beffc2e5a3afb15581b25 to your computer and use it in GitHub Desktop.
Start of a prototype for a text adventure game.
# Untitled Text Adventure prototype.
# Copyright 2024 Jay McGavren. All rights reserved.
class Thing
attr_accessor :name
def initialize(name:)
@name = name
end
end
class Mob < Thing
end
class Inventory
attr_accessor :items
def initialize
@items = []
end
end
class Area
attr_accessor :description
attr_accessor :things
attr_accessor :exits
def initialize(description: nil, things: [], exits: [])
@description, @things, @exits = description, things, exits
end
end
class Way
attr_accessor :destination
attr_accessor :direction
def initialize(destination:, direction:)
@destination, @direction = destination, direction
end
end
module Helpers
def self.parse_map(map_string)
map_string.lines.map{|line| line.chomp.split(//)}
end
def self.place_areas(map_array, map_areas)
map_array.map do |row|
row.map { |column| map_areas[column.to_sym] }
end
end
def self.connect_areas(map)
map = map_with_empty_boundary(map)
map.each_with_index do |row, y|
row.each_with_index do |area, x|
next unless area
if destination = map[y - 1][x]
area.exits << Way.new(destination:, direction: :north)
end
if destination = map[y + 1][x]
area.exits << Way.new(destination:, direction: :south)
end
if destination = map[y][x - 1]
area.exits << Way.new(destination:, direction: :west)
end
if destination = map[y][x + 1]
area.exits << Way.new(destination:, direction: :east)
end
end
end
end
# Add empty boundary to make math easier.
def self.map_with_empty_boundary(map)
map = map.dup
map.each_with_index{|row, i| map[i] = row.dup}
map.each{|row| row.unshift(nil); row.push(nil)}
map.unshift([]); map.push([])
map
end
end
map_string = <<~EOD
abc
defghimn
jkl
EOD
map_areas = {
a: Area.new(description: "forest"),
b: Area.new(description: "forest"),
c: Area.new(description: "forest"),
d: Area.new(description: "forest"),
e: Area.new(description: "clearing", things: [Thing.new(name: "axe")]),
f: Area.new(description: "clearing"),
g: Area.new(description: "clearing", things: [Thing.new(name: "boat")]),
h: Area.new(description: "clearing"),
i: Area.new(description: "forest"),
j: Area.new(description: "forest"),
k: Area.new(description: "forest"),
l: Area.new(description: "forest"),
m: Area.new(description: "lake"),
n: Area.new(description: "island"),
}
map = Helpers.place_areas(Helpers.parse_map(map_string), map_areas)
Helpers.connect_areas(map)
module Gathering
def inventory
@inventory ||= Inventory.new
end
def inventory=(value)
@inventory = value
end
def get(thing_name)
if thing = current_area.things.find{|t| t.name == thing_name.to_s}
inventory.items << thing
current_area.things.delete(thing)
puts "You now have the #{thing.name}."
else
puts "You don't see a(n) #{thing_name} here."
end
end
def axe; "axe"; end
def boat; "boat"; end
end
module Navigation
def go(direction)
if exit = current_area.exits.find{|exit| exit.direction == direction}
self.current_area = exit.destination
puts current_area.description
else
puts "You can't go that way."
end
end
def north; :north; end
def south; :south; end
def east; :east; end
def west; :west; end
def n; go north; end
def s; go south; end
def e; go east; end
def w; go west; end
end
module Vision
def exit_descriptions
current_area.exits.map do |exit|
"To the #{exit.direction} is #{exit.destination.description}."
end.join("\n")
end
def look
puts current_area.description
puts thing_descriptions
puts exit_descriptions
end
def thing_descriptions
return "You see nothing here." if current_area.things.empty?
"You see these things: " + current_area.things.map(&:name).join(", ")
end
end
require "pry"
class Session
include Navigation
include Gathering
include Vision
attr_accessor :current_area
def initialize(current_area:)
self.current_area = current_area
end
def play
binding.pry
end
end
Session.new(current_area: map[0][1]).play
__END__
# Livestock
- Cow: eats grass/hay, produces milk
- Chicken: eats corn, produces eggs
- Pig: eats almost anything, slaughter for meat
# Sample
@jaymcgavren
Copy link
Author

% bundle exec ruby '/Users/jay/Google Drive/My Drive/untitled_text_adventure/designs/farming.rb'

From: /Users/jay/Google Drive/My Drive/untitled_text_adventure/designs/farming.rb:103 Session#play:

    102: def play
 => 103:   binding.pry
    104: end

[1] pry(#<Session>)> look
forest
To the south is clearing.
To the east is forest.
=> nil
[2] pry(#<Session>)> go south
clearing
=> nil
[3] pry(#<Session>)> look
clearing
To the north is forest.
To the west is forest.
To the east is clearing.
=> nil
[4] pry(#<Session>)> go west
forest
=> nil
[5] pry(#<Session>)> look
forest
To the east is clearing.
=> nil
[6] pry(#<Session>)> go west
You can't go that way.
=> nil
[7] pry(#<Session>)>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment