skirmish 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MmI3OGUyNzQyMTE3NDcwOWFhNjFkNDZlZWRkMjkzZDNlMzQ1YWE0Yg==
5
+ data.tar.gz: !binary |-
6
+ OTY0NmQzMGNlMzhhMDMyNGVkYzFhMmJiZTdmNmRjYzlkNDljZDBkNA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NWIwZGY1MTE3ZjNjNmUzOTcwZTM5ZDYxYzFkMmY2ZDhjNmY5NjY5MmY2YjVm
10
+ YWE5ZmVlNjgyYzhkZmE4YTMzOWJhMmI2ZWVlM2U4ZmU3OTYwNjU2NTM2ODEx
11
+ NWNkZjRhYjhiM2U1NWYwMmNkYTY2MWI5YTg0MDE5ZTA4Y2VjZTg=
12
+ data.tar.gz: !binary |-
13
+ NjY3ZWVlZmM2MjgxZDAzMmU2MDIyNWM4ODAyMWI3Y2QyNzg3NTM2MDVmNWZj
14
+ MzdhMjU3ZjVlMzQzZDEwMzdhZTIxM2QwMTkxM2Q3NzM1NjZmZjkxYmU0YTY4
15
+ ZTEzYTYzYjg3Y2QzMWE0Mjg2Yzk3YzJjMDZlODhhODdjYmMzYjE=
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # skirmish is a single-player game in the style of CircleMUD.
4
+ # This script runs the game.
5
+ #
6
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
7
+ # Copyright:: Copyright (c) 2016 Andy Mikula
8
+ # License:: MIT
9
+
10
+ require_relative '../lib/skirmish'
11
+ Skirmish.play
@@ -0,0 +1,93 @@
1
+ # skirmish is a single-player game in the style of CircleMUD.
2
+ # This file holds the main class and game loop.
3
+ #
4
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
5
+ # Copyright:: Copyright (c) 2016 Andy Mikula
6
+ # License:: MIT
7
+
8
+ require 'curses'
9
+ require_relative 'skirmish/world'
10
+ require_relative 'skirmish/utilities'
11
+ require_relative 'skirmish/commands'
12
+ require_relative 'skirmish/character'
13
+
14
+ class Skirmish
15
+
16
+ # Set up the world and run the game loop
17
+ # TODO: Load the player / world state from a save file
18
+ def self.play
19
+ $world = World.new "lib/world/30.wld"
20
+ $player = Player.new
21
+ $input_buffer = Array.new
22
+ $command_history = Command_History.new
23
+
24
+ # TODO: Generate a number of mobiles that may or may not be a part of the
25
+ # player's quest. This shouldn't happen explicitly in the play method, but
26
+ # it does serve to demonstrate the functionality of the 'look' command
27
+ @mobile = Mobile.new("Bob", 1, 3014, "Bob is a character, just like you!", "bob")
28
+
29
+ # Set up the screen for curses and begin time
30
+ setup_screen
31
+ time = 0
32
+
33
+ # Main game loop
34
+ loop do
35
+ time += 1
36
+
37
+ case $player.state
38
+ # Player is entering their name
39
+ # TODO: Ask for confirmation on the name before continuing on.
40
+ when :CREATING
41
+ show_prompt("Welcome! What is your name?")
42
+ name = get_input
43
+
44
+ # TODO: Adding two newlines here is ugly.
45
+ unless name.nil?
46
+ $win.addstr("\n\n")
47
+ $player.name = name
48
+ cmd_stats($player, nil)
49
+ $player.state = :ROLLING
50
+ end
51
+
52
+ # Player is rolling stats
53
+ when :ROLLING
54
+ show_prompt("Is this acceptable (y/n)?")
55
+ choice = get_input
56
+ unless choice.nil?
57
+ $win.addstr("\n\n")
58
+ if choice =~ /\An\Z/i
59
+ $player.roll_stats
60
+ cmd_stats($player, nil)
61
+ elsif choice =~ /\Ay\Z/i
62
+ # Stats OK - set timeout for getch and show the player where
63
+ # they are in the world
64
+ $win.timeout = 100
65
+ $player.state = :PLAYING
66
+ cmd_look($player, "")
67
+ else
68
+ cmd_stats($player, nil)
69
+ end
70
+ end
71
+
72
+ # Player is in the game, walking around
73
+ when :PLAYING
74
+ # TODO: Pick a reasonable length of time for a 'tick'
75
+ if time % 20 == 0
76
+ time = 0
77
+ # Tick! Do world stuff
78
+ end
79
+
80
+ show_prompt(">")
81
+ handle_input(get_input)
82
+
83
+ # Player is engaged in a fight
84
+ when :FIGHTING
85
+ # Nothing yet...
86
+ end
87
+ end
88
+ end
89
+
90
+ if __FILE__ == $0
91
+ play
92
+ end
93
+ end
@@ -0,0 +1,79 @@
1
+ # skirmish is a single-player game in the style of CircleMUD.
2
+ # This file holds the Character class, as well as the Player and Mobile
3
+ # subclasses.
4
+ #
5
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
6
+ # Copyright:: Copyright (c) 2016 Andy Mikula
7
+ # License:: MIT
8
+
9
+ # The Character class represents a being that lives in the world. Human players
10
+ # and NPCs are both 'Character's.
11
+ class Character
12
+ attr_accessor :name, :height, :weight, :str, :dex, :con, :int, :wis, :cha,
13
+ :maxhp, :hp, :xp, :armour, :level, :state, :location, :description, :keywords
14
+
15
+ # Create the character, which by default begins at level one and starts life
16
+ # at the temple (room 3001)
17
+ def initialize(name="", initial_level=1, initial_location=3001, description="", keywords=Array.new)
18
+ @state = :CREATING
19
+ @name = name
20
+ @description = description
21
+ @keywords = keywords
22
+
23
+ roll_stats initial_level
24
+ @location = initial_location
25
+ $world.move_character(self, 0, initial_location)
26
+ end
27
+
28
+ # Roll stats for the character. This is based on the D&D 5e creation rules,
29
+ # with some tweaks.
30
+ def roll_stats(initial_level = 1)
31
+ size_roll = roll_dice(2, 10)
32
+ @height = 60 + size_roll #inches
33
+ @weight = 110 + roll_dice(2, 3) * size_roll #pounds
34
+
35
+ # Roll 3d6 for each attribute and sort the rolls by size
36
+ rolls = Array.new
37
+ 6.times do
38
+ rolls.push roll_dice(3,6)
39
+ end
40
+ rolls.sort! { |a, b| a <=> b }
41
+
42
+ # Assign rolls in the standard order for a 'fighter'
43
+ @str = rolls.pop()
44
+ @con = rolls.pop()
45
+ @dex = rolls.pop()
46
+ @cha = rolls.pop()
47
+ @wis = rolls.pop()
48
+ @int = rolls.pop()
49
+ @maxhp = @con + 10
50
+ @hp = @maxhp
51
+ @xp = 0
52
+ @armour = @dex + 10
53
+ @level = initial_level
54
+ end
55
+
56
+ # Character's attack each time is calculated based on a roll of 1d10 * level,
57
+ # or as otherwise specified
58
+ def attack(num=1, size=10)
59
+ return roll_dice(num, size) * @level
60
+ end
61
+ end
62
+
63
+ # A 'Player' is the human-controlled Character in the game
64
+ # TODO: Track playing time
65
+ class Player < Character
66
+ def initialize(name="", initial_level=1, initial_location=3001, description="You're...you!", keywords="self")
67
+ super(name, initial_level, initial_location, description, keywords)
68
+ @quest = nil
69
+ end
70
+ end
71
+
72
+ # A 'Mobile' is any non-player character in the game
73
+ # TODO: Write 'act' method for Mobile to be called on game ticks (or some
74
+ # multiple thereof)
75
+ class Mobile < Character
76
+ def initialize(name="", initial_level=1, initial_location=3001, description="", keywords=Array.new)
77
+ super(name, initial_level, initial_location, description, keywords)
78
+ end
79
+ end
@@ -0,0 +1,152 @@
1
+ # skirmish is a single-player game in the style of CircleMUD.
2
+ # This file holds player commands.
3
+ #
4
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
5
+ # Copyright:: Copyright (c) 2016 Andy Mikula
6
+ # License:: MIT
7
+
8
+ # Implementation of player commands. Each command must accept two arguments - a
9
+ # character object and the original input string
10
+
11
+ # TODO: Write commands as classes, so they can be aware of possible arguments
12
+ # and support tab-completion / notification to the user of incorrect arguments
13
+
14
+ # Move the character in the specified direction, if possible
15
+ def cmd_move_character(character, direction)
16
+ # Ask the world if there's a room in the direction we want to move
17
+ new_location = $world.get_destination(character.location,
18
+ case direction
19
+ when /\An/i then 0
20
+ when /\Ae/i then 1
21
+ when /\As/i then 2
22
+ when /\Aw/i then 3
23
+ when /\Au/i then 4
24
+ when /\Ad/i then 5
25
+ end
26
+ )
27
+ # If there's a room to go to, tell the world where the character is going, and
28
+ # let the character track it as well. If character is a player, either display
29
+ # their new location or a message telling them they are unable to move in that
30
+ # direction
31
+ unless new_location.nil?
32
+ $world.move_character character, character.location, new_location
33
+ character.location = new_location
34
+ if character.is_a?(Player)
35
+ cmd_look character, ""
36
+ end
37
+ else
38
+ if character.is_a?(Player)
39
+ print_line "You can't go that way!\n"
40
+ end
41
+ end
42
+ end
43
+
44
+ # List the available exits from the room the player is currently in
45
+ def cmd_list_exits(player, input)
46
+ exits = $world.get_exits player.location
47
+
48
+ exits_list = "[ Exits: "
49
+ until exits.empty? do
50
+ exits_list << "#{exits.shift} "
51
+ end
52
+ exits_list << "]\n"
53
+
54
+ print_line exits_list, :cyan
55
+ end
56
+
57
+ # List the commands available to the player
58
+ # TODO: Pretty this output up a little bit - even columns would be nice
59
+ def cmd_list_commands(player, input)
60
+ commands = $commands.keys
61
+
62
+ print_line commands.join(" ")
63
+ print_line
64
+ end
65
+
66
+ # For the Player's current location, display the room name, description, and any
67
+ # other characters who are in the room with the player
68
+ def cmd_look(player, input)
69
+
70
+ look_at = input.split[1..-1]
71
+
72
+ # If the player has specified a target / keyword, try to find it in the list
73
+ # of keywords on characters in the room
74
+ # TODO: Look at room keywords as well (i.e. 'look sign', etc.)
75
+ unless look_at.nil? || look_at.first.nil?
76
+ matches = $world.get_room_characters(player.location)
77
+ .select { |c| c.keywords =~ /\A#{Regexp.escape(look_at.first)}/i }
78
+ unless matches.first.nil?
79
+ print_line matches.first.description + "\n"
80
+ else
81
+ print_line "There is nothing to look at with that name.\n"
82
+ end
83
+ # No target specified - just show them the room name / description, any other
84
+ # characters who might be present, and the available exits
85
+ # TODO: Get the '...is standing here' description from the character
86
+ else
87
+ print_line $world.get_room_name(player.location), :cyan
88
+ print_line $world.get_room_description(player.location)
89
+ $world.get_room_characters(player.location).each do | char |
90
+ unless char.name == player.name
91
+ print_line char.name + " is standing here.", :white
92
+ end
93
+ end
94
+ cmd_list_exits player, nil
95
+ end
96
+ end
97
+
98
+ # Print the player's statistics to the screen
99
+ def cmd_stats(player, input)
100
+
101
+ # Height is stored in inches, but it's nice to have something like 5'10"
102
+ feet = player.height / 12
103
+ inches = player.height % 12
104
+
105
+ print_line("Your name is %s. You are %d'%d\" tall and you weigh %d lbs." %
106
+ [player.name, feet, inches, player.weight])
107
+ print_line("You are level %d and have %d experience points." %
108
+ [player.level, player.xp])
109
+ print_line("============================================================")
110
+ print_line("Hitpoints: %6d / %d" % [player.hp, player.maxhp])
111
+ print_line("Attack: %6d - %2d" % [player.level, player.level * 10])
112
+ print_line("Armour: %6d" % player.armour)
113
+ print_line("============================================================")
114
+ print_line("Strength: %6d Charisma: %6d" % [player.str, player.cha])
115
+ print_line("Constitution:%6d Wisdom: %6d" % [player.con, player.wis])
116
+ print_line("Dexterity: %6d Intelligence:%6d" % [player.dex, player.int])
117
+ print_line
118
+ end
119
+
120
+ # Quit the game. Make sure the player is sure! We don't want to quit on an
121
+ # accidental 'q', for example
122
+ # TODO: Save player / world state
123
+ def cmd_quit(player, input)
124
+ unless input =~ /quit/i
125
+ print_line "You must type the entire word 'quit' to quit.\n"
126
+ else
127
+ print_line "Until next time..."
128
+ $win.refresh
129
+ sleep 3
130
+ $win.close
131
+ exit
132
+ end
133
+ end
134
+
135
+ # The possible command strings and their associated methods. To be able to use
136
+ # a new command, it must be implemented above and added here. Ruby remembers the
137
+ # order in which keys are added to a hash, which is convenient - we always match
138
+ # the first key we see. As a result, entries higher up in the list have greater
139
+ # precedence (making sure we match 'north' on 'n' instead of 'nap', for example)
140
+ $commands = { "north" => method(:cmd_move_character),
141
+ "east" => method(:cmd_move_character),
142
+ "south" => method(:cmd_move_character),
143
+ "west" => method(:cmd_move_character),
144
+ "up" => method(:cmd_move_character),
145
+ "down" => method(:cmd_move_character),
146
+
147
+ "commands" => method(:cmd_list_commands),
148
+ "exits" => method(:cmd_list_exits),
149
+ "look" => method(:cmd_look),
150
+ "stats" => method(:cmd_stats),
151
+ "quit" => method(:cmd_quit)
152
+ }
@@ -0,0 +1,186 @@
1
+ # skirmish is a single-player game in the style of CircleMUD.
2
+ # This file holds the Command_History class, as well as functions for I/O, die
3
+ # rolling, and the like.
4
+ #
5
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
6
+ # Copyright:: Copyright (c) 2016 Andy Mikula
7
+ # License:: MIT
8
+
9
+ # This class stores the commands that have been entered by the player, so we can
10
+ # have bash-style command history.
11
+ class Command_History
12
+ def initialize
13
+ @history = Array.new
14
+ @position = 0 # The current 'position' in the list of commands
15
+ end
16
+
17
+ # The user entered a command - store it to the list and update the pointer
18
+ def add_command(command)
19
+ @history.push command
20
+ @position = @history.length - 1
21
+ end
22
+
23
+ # Unless we're already looking at the first item in the list, return the
24
+ # command at the current position and decrement the 'position' pointer
25
+ def get_previous
26
+ unless @position == 0
27
+ previous_command = @history[@position]
28
+ @position -= 1
29
+ return previous_command
30
+ else
31
+ return nil
32
+ end
33
+ end
34
+
35
+ # Unless we're already looking at the most recent item in the list, increment
36
+ # the 'position' pointer and return the command at the new position
37
+ def get_next
38
+ unless @position == @history.length - 1
39
+ @position += 1
40
+ next_command = @history[@position]
41
+ return next_command
42
+ else
43
+ return nil
44
+ end
45
+ end
46
+ end
47
+
48
+ # Look for input from the player, and return it once they have pressed 'enter'.
49
+ # Otherwise, return nil
50
+ def get_input
51
+ case char = $win.getch
52
+ # Backspace: Remove the last character from the input buffer
53
+ when Curses::KEY_BACKSPACE
54
+ $input_buffer.pop
55
+ return nil
56
+
57
+ # Up: Look for the previous command in the command history. If something
58
+ # exists, clear the input buffer and replace it with the last command
59
+ when Curses::KEY_UP
60
+ previous_command = $command_history.get_previous
61
+ unless previous_command.nil?
62
+ $input_buffer.clear
63
+ previous_command.each_char { |chr| $input_buffer.push chr }
64
+ end
65
+ return nil
66
+
67
+ # Down: Look for the next command in the command history. If something
68
+ # exists, clear the input buffer and replace it with the next command
69
+ when Curses::KEY_DOWN
70
+ next_command = $command_history.get_next
71
+ unless next_command.nil?
72
+ $input_buffer.clear
73
+ next_command.each_char { |chr| $input_buffer.push chr }
74
+ end
75
+ return nil
76
+
77
+ # Tab: See if there's a command that will match to what's currently in the
78
+ # input buffer. If there is, clear the buffer and replace with the command.
79
+ # If not, do nothing
80
+ when 9
81
+ possible_commands = $commands.select { |c| c =~ /\A#{Regexp.escape($input_buffer.join)}/i }
82
+ # TODO: Look for a space in the buffer instead of this horribe hack.
83
+ # We don't want to tab-complete the argument to a command
84
+ unless possible_commands.nil? or possible_commands.first.nil?
85
+ $input_buffer.clear
86
+ possible_commands.first.first.each_char { |chr| $input_buffer.push chr }
87
+ end
88
+ return nil
89
+
90
+ # Enter: Add the input buffer to the command history, and return the input
91
+ # as a string
92
+ when 10 , 13
93
+ input = $input_buffer.join
94
+ $input_buffer.clear
95
+ $command_history.add_command input
96
+ return input
97
+
98
+ # Any printable character: Add the character to the input buffer
99
+ when /[[:print:]]/
100
+ $input_buffer << char
101
+ return nil
102
+ end
103
+ end
104
+
105
+ # Curses screen setup and color pair definitions
106
+ def setup_screen
107
+ Curses.init_screen
108
+ Curses.start_color
109
+ Curses.cbreak
110
+ Curses.noecho
111
+ Curses.nl
112
+
113
+ # Color pairs. Arguments: color_number, foreground color, background color
114
+ Curses.init_pair 1, Curses::COLOR_GREEN, Curses::COLOR_BLACK
115
+ Curses.init_pair 2, Curses::COLOR_CYAN, Curses::COLOR_BLACK
116
+ Curses.init_pair 3, Curses::COLOR_WHITE, Curses::COLOR_BLACK
117
+
118
+ # Set up the window to fill the whole terminal
119
+ $win = Curses::Window.new(0, 0, 0, 0)
120
+ # Set the initial color to green on black
121
+ $win.color_set(1)
122
+ # Allow the screen to scroll, and allow the terminal to scroll as well
123
+ $win.scrollok true
124
+ $win.idlok true
125
+ # Allow capture of non-alpha key inputs (arrows, enter, etc.)
126
+ $win.keypad = true
127
+ end
128
+
129
+ # Find a command to invoke based on input from a character.
130
+ def handle_input(input)
131
+ return if input.nil?
132
+
133
+ input.chomp!
134
+
135
+ # Print functions clear the current line, so if we're handling input, we need
136
+ # to move down a few lines so we can see what we entered on our screen.
137
+ $win.addstr("\n\n")
138
+
139
+ if input.length == 0
140
+ print_line("Please enter a valid command. A list of commands is available by typing 'commands'.\n")
141
+ return nil
142
+ end
143
+
144
+ # See if we can find a command key that matches the first word of the input
145
+ matches = $commands.select { |c| c =~ /\A#{Regexp.escape(input.split.first)}/i }
146
+ command = matches.first
147
+
148
+ unless command.nil?
149
+ # We have a match! Call the method associated with the command
150
+ return command[1].call($player, input)
151
+ else
152
+ print_line("\"#{input}\" is not a valid command. A list of commands is available by typing 'commands'.\n")
153
+ end
154
+ end
155
+
156
+ # Show a prompt to the player
157
+ def show_prompt(prompt=">")
158
+ $win.color_set(3)
159
+ $win.setpos($win.cury, 0)
160
+ $win.deleteln
161
+ $win.addstr(prompt + " " + $input_buffer.join)
162
+ $win.color_set(1)
163
+ end
164
+
165
+ # Print a line to the screen.
166
+ def print_line(line = "", color = :green)
167
+ case color
168
+ when :green
169
+ $win.color_set(1)
170
+ when :cyan
171
+ $win.color_set(2)
172
+ when :white
173
+ $win.color_set(3)
174
+ end
175
+
176
+ $win.setpos($win.cury, 0)
177
+ $win.deleteln
178
+ $win.addstr(line + "\n")
179
+
180
+ $win.color_set(1)
181
+ end
182
+
183
+ # Roll number_of_dice with size_of_dice sides, and return the result
184
+ def roll_dice(number_of_dice, size_of_dice)
185
+ (1..number_of_dice).inject(0){ | sum, _ | sum + rand(1..size_of_dice) }
186
+ end
@@ -0,0 +1,129 @@
1
+ # skirmish is a single-player game in the style of CircleMUD.
2
+ # This file holds the World class, as well as structures to hold room and
3
+ # description data.
4
+ #
5
+ # Author:: Andy Mikula (mailto:andy@andymikula.ca)
6
+ # Copyright:: Copyright (c) 2016 Andy Mikula
7
+ # License:: MIT
8
+
9
+ class World
10
+
11
+ # Create the world, using the specified file to load rooms.
12
+ # TODO: Load multiple room files from a folder
13
+ # TODO: Write world files in json or something similar
14
+ def initialize(world_file)
15
+ # Set up collections for rooms, characters, and potential mobile names
16
+ # TODO: Move @names to mobile class for use during creation
17
+ @rooms = Hash.new
18
+ @characters = Array.new
19
+ #@names = Array.new
20
+
21
+ # Not used currently
22
+ #f = File.open("lib/mobiles/names") or die "Unable to open 'names' file."
23
+ #f.each_line {|name| @names.push name}
24
+ #f.close
25
+
26
+ # Parse the CircleMUD .wld file. This is ugly, and I do not recommend
27
+ # touching it. Each room is given a name, description, and exits, and is
28
+ # added to the rooms list
29
+ # TODO: Get extra description data (signs, etc.)
30
+ File.read(world_file).split(/^\#/).drop(1).each do |chunk|
31
+ room = chunk.split(/\r?\n|\r/)
32
+ new_room = Room.new
33
+
34
+ room_number = room.shift.to_i
35
+ new_room.name = room.shift[0..-2]
36
+
37
+ new_room.description = room.shift
38
+ line = room.shift
39
+ until line == "~"
40
+ new_room.description.concat "\n"
41
+ new_room.description.concat line
42
+ line = room.shift
43
+ end
44
+
45
+ 2.times {line = room.shift}
46
+
47
+ until line == "S"
48
+ if line[0] == "D"
49
+ direction = line[1]
50
+ dest = room.shift
51
+ dest = room.shift until dest == "~"
52
+ room.shift
53
+ dest = room.shift.split[-1]
54
+ new_room.direction_data.store(direction.to_i, dest.to_i)
55
+ line = room.shift
56
+ else
57
+ line = room.shift until line == "~"
58
+ line = room.shift
59
+ end
60
+ end
61
+ @rooms[room_number] = new_room
62
+ end
63
+ end
64
+
65
+ # If we know about the room in question, return its name
66
+ def get_room_name(room_number)
67
+ @rooms.key?(room_number) ? @rooms[room_number].name : nil
68
+ end
69
+
70
+ # If we know about the room in question, return its description
71
+ def get_room_description(room_number)
72
+ @rooms.key?(room_number) ? @rooms[room_number].description : nil
73
+ end
74
+
75
+ # If we know about the room in question, and have data for the room in the
76
+ # specified direction, return the number of the destination room. This is
77
+ # likely a bit of an abuse of the ternary operator
78
+ def get_destination(room_number, direction)
79
+ @rooms.key?(room_number) && @rooms.key?(@rooms[room_number].direction_data[direction]) ? @rooms[room_number].direction_data[direction] : nil
80
+ end
81
+
82
+ # Return the list of characters who are currently in the specified room
83
+ def get_room_characters(room_number)
84
+ return @rooms[room_number].characters
85
+ end
86
+
87
+ # Move a character from original_location to new_location - each room's
88
+ # 'characters' list should contain each character who is currently there
89
+ def move_character(character, original_location, new_location)
90
+ if @rooms.key?(original_location)
91
+ @rooms[original_location].characters.delete(character)
92
+ end
93
+ @rooms[new_location].characters.push character
94
+ end
95
+
96
+ # Return an array of characters signifying the possible exits from the
97
+ # specified room
98
+ def get_exits(room_number)
99
+ directions = ["n", "e", "s", "w", "u", "d"]
100
+ exits = Array.new
101
+
102
+ 6.times do |i|
103
+ if @rooms.key?(@rooms[room_number].direction_data[i])
104
+ exits.push(directions[i])
105
+ end
106
+ end
107
+ return exits
108
+ end
109
+ end
110
+
111
+ # This does not need to be a whole class by itself, and is not currently used
112
+ # TODO: Make Room.extra_descriptions a hash, so we can store
113
+ # keyword => description pairs
114
+ #class DescriptionData
115
+ # @keyword
116
+ # @description
117
+ #end
118
+
119
+ # A class to represent a room. A room is uniquely identified by its number,
120
+ # knows which characters and objects are in it, and knows which rooms are
121
+ # connected to it and in which direction
122
+ class Room
123
+ attr_accessor :number, :name, :description, :direction_data, :characters
124
+
125
+ def initialize
126
+ @direction_data = Hash.new
127
+ @characters = Array.new
128
+ end
129
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skirmish
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andy Mikula
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A single-player text-based game compatible with CircleMUD world files
14
+ email: andy@andymikula.ca
15
+ executables:
16
+ - skirmish
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/skirmish
21
+ - lib/skirmish.rb
22
+ - lib/skirmish/character.rb
23
+ - lib/skirmish/commands.rb
24
+ - lib/skirmish/utilities.rb
25
+ - lib/skirmish/world.rb
26
+ homepage: http://andy-j.github.io/skirmish
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.4.8
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: skirmish
50
+ test_files: []