monkeymusic 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.
- data/Gemfile +6 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +21 -0
- data/README.markdown +38 -0
- data/bin/monkeymusic +5 -0
- data/levels/testlevel.rb +28 -0
- data/levels/testlevel_maze.rb +24 -0
- data/levels/the_last_crusade.rb +21 -0
- data/levels/travelling_salesmonkeys.rb +0 -0
- data/lib/monkey_music/game.rb +27 -0
- data/lib/monkey_music/level.rb +91 -0
- data/lib/monkey_music/level_loader.rb +64 -0
- data/lib/monkey_music/player.rb +41 -0
- data/lib/monkey_music/recommendation_loader.rb +91 -0
- data/lib/monkey_music/runner.rb +169 -0
- data/lib/monkey_music/score_system.rb +37 -0
- data/lib/monkey_music/toplist_loader.rb +68 -0
- data/lib/monkey_music/ui/browser_ui.rb +36 -0
- data/lib/monkey_music/ui/console_ui.rb +31 -0
- data/lib/monkey_music/units/base.rb +71 -0
- data/lib/monkey_music/units/monkey.rb +85 -0
- data/lib/monkey_music/units/track.rb +33 -0
- data/lib/monkey_music/units/user.rb +38 -0
- data/lib/monkey_music/units/wall.rb +4 -0
- data/lib/monkey_music.rb +20 -0
- data/users/synth.rb +7 -0
- data/users/synth.yaml +1682 -0
- metadata +136 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
em-websocket (0.5.0)
|
5
|
+
eventmachine (>= 0.12.9)
|
6
|
+
http_parser.rb (~> 0.5.3)
|
7
|
+
eventmachine (1.0.3)
|
8
|
+
ffi (1.8.1)
|
9
|
+
hallon (0.18.2)
|
10
|
+
ffi (~> 1.8)
|
11
|
+
spotify (~> 12.5.1)
|
12
|
+
weak_observable (~> 1.0)
|
13
|
+
http_parser.rb (0.5.3)
|
14
|
+
json (1.7.7)
|
15
|
+
libspotify (12.1.51.3)
|
16
|
+
rack (1.5.2)
|
17
|
+
ref (1.0.4)
|
18
|
+
spotify (12.5.1)
|
19
|
+
ffi (~> 1.0, >= 1.0.11)
|
20
|
+
libspotify (~> 12.1.51)
|
21
|
+
weak_observable (1.0.1)
|
22
|
+
ref (~> 1.0.0)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
em-websocket
|
29
|
+
hallon
|
30
|
+
json
|
31
|
+
rack
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010 Ryan Bates
|
2
|
+
2013 Oscar Söderlund
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Monkey Music
|
2
|
+
============
|
3
|
+
|
4
|
+
This is the runtime for a programming contest, it's a work in progress.
|
5
|
+
|
6
|
+
To test-drive:
|
7
|
+
|
8
|
+
./bin/monkeymusic --user users/poscar.yaml --level levels/testlevel.rb --player-file p1 --player-name p1 --player-file p1 --player-name p2
|
9
|
+
|
10
|
+
Rules
|
11
|
+
-----
|
12
|
+
|
13
|
+
### Which monkey gets to move first?
|
14
|
+
|
15
|
+
Every round, all monkeys are put into a Fisher-Yates shuffled array, and
|
16
|
+
the monkeys will be allowed to move in order of increasing index.
|
17
|
+
|
18
|
+
Input
|
19
|
+
-----
|
20
|
+
|
21
|
+
One line with one positive integer, id, that identifies your monkey.
|
22
|
+
One line with two positive integers, w, h. The width and the
|
23
|
+
height of the level.
|
24
|
+
h lines with w comma-separated strings each. Each string represents a
|
25
|
+
space in the level.
|
26
|
+
|
27
|
+
A space can contain the following:
|
28
|
+
|
29
|
+
A monkey, on the form M#id, the letter M followed by a hash followed by the id of a monkey.
|
30
|
+
A basket, on the form B#id, the letter B followed by a hash followed by
|
31
|
+
A track URI, on the form spotify:track:XXXXXXXXXXXXXXX.
|
32
|
+
the id of the monkey the basket belongs to.
|
33
|
+
A palm tree, on the form P.
|
34
|
+
|
35
|
+
Output
|
36
|
+
------
|
37
|
+
|
38
|
+
One of the characters ['N','W','E','S'] followed by a line-break '\n'.
|
data/bin/monkeymusic
ADDED
data/levels/testlevel.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
carrying_capacity 3
|
2
|
+
metadata_requests_per_turn 2
|
3
|
+
max_turns 100
|
4
|
+
|
5
|
+
legend({
|
6
|
+
"1" => Monkey.player(1),
|
7
|
+
"2" => Monkey.player(2),
|
8
|
+
"X" => Track.worth(-2),
|
9
|
+
"x" => Track.worth(-1),
|
10
|
+
"l" => Track.worth(1),
|
11
|
+
"t" => Track.worth(2),
|
12
|
+
"T" => Track.worth(3),
|
13
|
+
"U" => User,
|
14
|
+
})
|
15
|
+
|
16
|
+
layout <<LAYOUT
|
17
|
+
...........
|
18
|
+
..x........
|
19
|
+
...........
|
20
|
+
.......T...
|
21
|
+
1..........
|
22
|
+
...t......U
|
23
|
+
2..........
|
24
|
+
.......l...
|
25
|
+
...........
|
26
|
+
..X........
|
27
|
+
...........
|
28
|
+
LAYOUT
|
@@ -0,0 +1,24 @@
|
|
1
|
+
width 25
|
2
|
+
height 11
|
3
|
+
max_turns 200
|
4
|
+
carrying_capacity 100
|
5
|
+
|
6
|
+
legend({
|
7
|
+
"1" => Monkey,
|
8
|
+
"!" => Track,
|
9
|
+
"#" => Wall,
|
10
|
+
})
|
11
|
+
|
12
|
+
layout <<LAYOUT
|
13
|
+
#########################
|
14
|
+
#! # # !#
|
15
|
+
### ###### # #######
|
16
|
+
# # # #
|
17
|
+
# ### ###### # #
|
18
|
+
# #! # # # #
|
19
|
+
# # # ### # # #
|
20
|
+
# # # # #1 # #
|
21
|
+
# ###### ########## #
|
22
|
+
# !# #
|
23
|
+
#########################
|
24
|
+
LAYOUT
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# In this level, the monkeys ability to navigate a maze and pick
|
2
|
+
# the best out of many tracks is tested. Do not choose poorly...
|
3
|
+
|
4
|
+
width 20
|
5
|
+
height 10
|
6
|
+
capacity 1
|
7
|
+
|
8
|
+
legend({
|
9
|
+
"T" => Tube,
|
10
|
+
"M" => Monkey,
|
11
|
+
"s" => Track,
|
12
|
+
"#" => Wall,
|
13
|
+
})
|
14
|
+
|
15
|
+
layout <<EOS
|
16
|
+
T..#.....#.....#...s
|
17
|
+
...#..#..#..#..#...s
|
18
|
+
.M.#..#..#..#..#...s
|
19
|
+
...#..#..#..#..#...s
|
20
|
+
......#.....#......s
|
21
|
+
EOS
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module MonkeyMusic
|
4
|
+
class Game
|
5
|
+
|
6
|
+
def initialize(level, players, ui)
|
7
|
+
@level = level
|
8
|
+
@players = players
|
9
|
+
@ui = ui
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
@level.max_turns.times do
|
14
|
+
if @level.complete?
|
15
|
+
break
|
16
|
+
end
|
17
|
+
@ui.update(@level)
|
18
|
+
# Query players for moves
|
19
|
+
@players.each { |p| p.query_move! }
|
20
|
+
# Move players in random order
|
21
|
+
@players.shuffle.each { |p| p.move! }
|
22
|
+
end
|
23
|
+
@ui.update(@level)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module MonkeyMusic
|
4
|
+
class Level
|
5
|
+
attr_accessor :width, :height, :max_turns
|
6
|
+
attr_reader :players
|
7
|
+
attr_reader :user
|
8
|
+
|
9
|
+
def initialize(players, user)
|
10
|
+
@players = players
|
11
|
+
@user = user
|
12
|
+
@width = 0
|
13
|
+
@height = 0
|
14
|
+
@units = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(unit, x, y)
|
18
|
+
unit.place!(self, x, y)
|
19
|
+
unit.assign_id
|
20
|
+
@units << unit
|
21
|
+
end
|
22
|
+
|
23
|
+
def at(x, y)
|
24
|
+
@units.detect { |u| u.at?(x, y) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?(x, y)
|
28
|
+
at(x, y).nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def complete?
|
32
|
+
(@units.detect { |u| u.kind_of? Track }).nil? &&
|
33
|
+
(@players.detect { |p| p.monkey.carrying.count > 0 }).nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
def remove(unit)
|
37
|
+
@units.reject! { |u| u == unit }
|
38
|
+
end
|
39
|
+
|
40
|
+
def out_of_bounds?(x, y)
|
41
|
+
x < 0 || y < 0 || x > @width-1 || y > @height-1
|
42
|
+
end
|
43
|
+
|
44
|
+
def accessible?(x, y)
|
45
|
+
not out_of_bounds?(x, y) && empty?(x, y)
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_from_file(file)
|
49
|
+
LevelLoader.new(self).instance_eval(IO.read(file))
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
rows = []
|
55
|
+
rows << " " + ("=" * @width)
|
56
|
+
@height.times do |y|
|
57
|
+
row = ["|"]
|
58
|
+
@width.times do |x|
|
59
|
+
unit = at(x, y)
|
60
|
+
row << if unit then unit.to_s else ' ' end
|
61
|
+
end
|
62
|
+
row << "|"
|
63
|
+
rows << row.join
|
64
|
+
end
|
65
|
+
rows << " " + ("=" * @width)
|
66
|
+
rows.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
def serialize
|
70
|
+
rows = []
|
71
|
+
@height.times do |y|
|
72
|
+
row = []
|
73
|
+
@width.times do |x|
|
74
|
+
unit = at(x, y)
|
75
|
+
row << if unit then unit.serialize else '_' end
|
76
|
+
end
|
77
|
+
rows << row.join(",")
|
78
|
+
end
|
79
|
+
rows.join("\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
def as_json
|
83
|
+
{
|
84
|
+
:width => @width,
|
85
|
+
:height => @height,
|
86
|
+
:units => @units,
|
87
|
+
}.to_json
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module MonkeyMusic
|
2
|
+
#
|
3
|
+
# LevelLoader defines a DSL for building levels in a ruby file
|
4
|
+
#
|
5
|
+
class LevelLoader
|
6
|
+
def initialize(level)
|
7
|
+
@level = level
|
8
|
+
@legend = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def max_turns(max_turns)
|
12
|
+
@level.max_turns = max_turns
|
13
|
+
end
|
14
|
+
|
15
|
+
def metadata_requests_per_turn(n)
|
16
|
+
@metadata_requests_per_turn = n
|
17
|
+
end
|
18
|
+
|
19
|
+
def carrying_capacity(capacity)
|
20
|
+
@level.players.each { |p| p.monkey.capacity = capacity }
|
21
|
+
end
|
22
|
+
|
23
|
+
def legend(legend)
|
24
|
+
@legend = legend
|
25
|
+
end
|
26
|
+
|
27
|
+
def layout(layout)
|
28
|
+
# Transform layout into x y indexed array
|
29
|
+
units = (layout.lines.map { |l| l.chomp.split(//) }).transpose
|
30
|
+
@level.width = units[0].length
|
31
|
+
@level.height = units.length
|
32
|
+
# Add units from layout to level
|
33
|
+
@level.height.times do |y|
|
34
|
+
@level.width.times do |x|
|
35
|
+
curr_character = units[x][y]
|
36
|
+
unit = parse_character(curr_character)
|
37
|
+
@level.add(unit, x, y) if unit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse_character(character)
|
45
|
+
klass = @legend[character]
|
46
|
+
if klass
|
47
|
+
unit = if (klass <= Monkey)
|
48
|
+
klass.from_players(@level.players)
|
49
|
+
elsif klass <= Track
|
50
|
+
klass.from_user(@level.user)
|
51
|
+
elsif klass == User
|
52
|
+
@level.user
|
53
|
+
else
|
54
|
+
klass.new
|
55
|
+
end
|
56
|
+
if unit
|
57
|
+
unit.character = character
|
58
|
+
unit
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module MonkeyMusic
|
2
|
+
class Player
|
3
|
+
attr_accessor :monkey
|
4
|
+
|
5
|
+
def initialize(file)
|
6
|
+
@file = file
|
7
|
+
@monkey = Monkey.new()
|
8
|
+
end
|
9
|
+
|
10
|
+
def query_move!
|
11
|
+
IO.popen(@file, "r+") do |io|
|
12
|
+
io.puts @monkey.serialize
|
13
|
+
io.puts @monkey.remaining_capacity
|
14
|
+
io.puts @monkey.level.width
|
15
|
+
io.puts @monkey.level.height
|
16
|
+
io.puts @monkey.level.serialize
|
17
|
+
move = io.gets
|
18
|
+
@next_move = parse_move(move) if move
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_move(s)
|
23
|
+
case s.chomp
|
24
|
+
when "N" then :north
|
25
|
+
when "W" then :west
|
26
|
+
when "E" then :east
|
27
|
+
when "S" then :south
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def move!
|
32
|
+
@monkey.move! @next_move if @next_move
|
33
|
+
@next_move = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
"#{@monkey.name}: #{@file}"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'hallon'
|
2
|
+
|
3
|
+
module MonkeyMusic
|
4
|
+
class RecommendationLoader
|
5
|
+
|
6
|
+
def initialize(loaded_toplists, load_factor = 5)
|
7
|
+
@loaded_toplists = loaded_toplists
|
8
|
+
@load_factor = load_factor
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_for_user!(user)
|
12
|
+
@user = user
|
13
|
+
puts "Loading recommendations from album toplist..."
|
14
|
+
load_recommendations_from_albums!
|
15
|
+
puts "Loading recommendations from artist toplist..."
|
16
|
+
load_recommendations_from_artists!
|
17
|
+
puts "Loading recommendations from track toplist albums..."
|
18
|
+
load_recommendations_from_top_track_albums!
|
19
|
+
puts "Loading recommendations from track toplist..."
|
20
|
+
load_recommendations_from_already_heard!
|
21
|
+
puts "Loading recommendations from disliked artists..."
|
22
|
+
load_recommendations_from_disliked!
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def load_recommendations_from_albums!
|
28
|
+
@loaded_toplists[:top_albums].each do |album|
|
29
|
+
puts "Browsing #{album.name}..."
|
30
|
+
browse = album.browse
|
31
|
+
browse.load unless browse.loaded?
|
32
|
+
browse.tracks.first(@load_factor).each do |rec|
|
33
|
+
@user.recommendations << parse_track(rec)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_recommendations_from_artists!
|
39
|
+
@loaded_toplists[:top_artists].each do |artist|
|
40
|
+
puts "Browsing #{artist.name}..."
|
41
|
+
browse = artist.browse(:no_albums)
|
42
|
+
browse.load unless browse.loaded?
|
43
|
+
browse.top_hits.first(@load_factor).each do |rec|
|
44
|
+
@user.recommendations << parse_track(rec)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def load_recommendations_from_top_track_albums!
|
50
|
+
@loaded_toplists[:top_track_albums].each do |album|
|
51
|
+
puts "Browsing #{album.name}..."
|
52
|
+
browse = album.browse
|
53
|
+
browse.load unless browse.loaded?
|
54
|
+
browse.tracks.first(@load_factor).each do |rec|
|
55
|
+
@user.recommendations << parse_track(rec)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_recommendations_from_already_heard!
|
61
|
+
@loaded_toplists[:top_tracks].each do |track|
|
62
|
+
@user.recommendations << parse_track(track)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def load_recommendations_from_disliked!
|
67
|
+
@loaded_toplists[:disliked].each do |artist|
|
68
|
+
puts "Browsing #{artist.name}..."
|
69
|
+
browse = artist.browse(:no_albums)
|
70
|
+
browse.load unless browse.loaded?
|
71
|
+
browse.top_hits.first(@load_factor).each do |rec|
|
72
|
+
@user.recommendations << parse_track(rec)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_track(track)
|
78
|
+
album = track.album.load
|
79
|
+
artist = track.artist.load
|
80
|
+
user_track = Track.new
|
81
|
+
user_track.uri = track.to_link.to_str
|
82
|
+
user_track.name = track.name
|
83
|
+
user_track.artist = artist.name
|
84
|
+
user_track.album = album.name
|
85
|
+
user_track.popularity = track.popularity
|
86
|
+
user_track.year = album.release_year
|
87
|
+
user_track
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module MonkeyMusic
|
4
|
+
class Runner
|
5
|
+
|
6
|
+
def initialize(arguments)
|
7
|
+
@arguments = arguments
|
8
|
+
@opt_parser = OptionParser.new
|
9
|
+
@players = []
|
10
|
+
@delay = 1
|
11
|
+
init_parser(@opt_parser)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
@opt_parser.parse!
|
16
|
+
if generate_user?
|
17
|
+
# Create user
|
18
|
+
user = User.new
|
19
|
+
# Connect to libspotify
|
20
|
+
Hallon.load_timeout = 0
|
21
|
+
session = Hallon::Session.initialize(IO.read(@spotify_appkey_file))
|
22
|
+
session.login!(@spotify_account, @spotify_password)
|
23
|
+
# Load toplists
|
24
|
+
puts "Loading toplists from #{@toplist_file}..."
|
25
|
+
toplist_loader = ToplistLoader.new(@toplist_file)
|
26
|
+
toplist_loader.load_for_user!(user)
|
27
|
+
# Generate recommendations
|
28
|
+
puts "Loading recommendations..."
|
29
|
+
loaded_toplists = toplist_loader.loaded_toplists
|
30
|
+
recommendation_loader = RecommendationLoader.new(loaded_toplists)
|
31
|
+
recommendation_loader.load_for_user!(user)
|
32
|
+
# Disconnect from libspotify
|
33
|
+
session.logout!
|
34
|
+
# Evaluate recommendations
|
35
|
+
puts "Evaluating recommendations..."
|
36
|
+
score_system = ScoreSystem.new
|
37
|
+
score_system.evaluate_user_recommendations!(user)
|
38
|
+
# Dump and print the user
|
39
|
+
File.open(@out_file, 'w') do |f|
|
40
|
+
f.write(user.dump)
|
41
|
+
end
|
42
|
+
puts "====="
|
43
|
+
puts "DONE!"
|
44
|
+
puts "====="
|
45
|
+
puts "Loaded tracks:"
|
46
|
+
user.recommendations.group_by(&:multiplier).sort.each do |k,v|
|
47
|
+
puts "#Multiplier #{k}:\t#{v.length}"
|
48
|
+
end
|
49
|
+
exit
|
50
|
+
elsif not game_is_playable?
|
51
|
+
puts @opt_parser
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
# Load user
|
55
|
+
user = User.new
|
56
|
+
user.load_from_file(@user_file)
|
57
|
+
# Load level
|
58
|
+
level = Level.new(@players, user)
|
59
|
+
level.load_from_file(@level_file)
|
60
|
+
## Initialize UI
|
61
|
+
if browser_ui?
|
62
|
+
print "Using browser UI. Press the enter key to start game. "
|
63
|
+
gets
|
64
|
+
puts "Starting game..."
|
65
|
+
ui = BrowserUI.new(@delay)
|
66
|
+
else
|
67
|
+
ui = ConsoleUI.new(@delay)
|
68
|
+
end
|
69
|
+
## Start game
|
70
|
+
@game = Game.new(level, @players, ui)
|
71
|
+
@game.start
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def generate_user?
|
77
|
+
(defined? @toplist_file) &&
|
78
|
+
(defined? @out_file) &&
|
79
|
+
(defined? @spotify_appkey_file) &&
|
80
|
+
(defined? @spotify_account) &&
|
81
|
+
(defined? @spotify_password)
|
82
|
+
end
|
83
|
+
|
84
|
+
def game_is_playable?
|
85
|
+
(defined? @user_file) &&
|
86
|
+
(defined? @level_file) &&
|
87
|
+
(not @players.empty?)
|
88
|
+
end
|
89
|
+
|
90
|
+
def browser_ui?
|
91
|
+
@browser_ui == true
|
92
|
+
end
|
93
|
+
|
94
|
+
def init_parser(opts)
|
95
|
+
opts.banner = 'Usage: monkeymusic [options]'
|
96
|
+
|
97
|
+
opts.on('-l',
|
98
|
+
'--level LEVEL',
|
99
|
+
'The level to play.') do |file|
|
100
|
+
@level_file = File.join(Dir.getwd, file)
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.on('-u',
|
104
|
+
'--user USER',
|
105
|
+
'The user the players will recommend music for.') do |user|
|
106
|
+
@user_file = File.join(Dir.getwd, user)
|
107
|
+
end
|
108
|
+
|
109
|
+
opts.on('-p',
|
110
|
+
'--player FILE',
|
111
|
+
'The path to a player program.') do |file|
|
112
|
+
player_file = File.join(Dir.getwd, file)
|
113
|
+
@players << Player.new(player_file)
|
114
|
+
end
|
115
|
+
|
116
|
+
opts.on('-n',
|
117
|
+
'--player-name NAME',
|
118
|
+
'Set the name of the last entered player.') do |name|
|
119
|
+
@players[-1].monkey.name = name unless @players.empty?
|
120
|
+
end
|
121
|
+
|
122
|
+
opts.on('-d', '--delay DELAY', OptionParser::DecimalNumeric,
|
123
|
+
'The delay (in seconds) between each round.') do |delay|
|
124
|
+
@delay = delay
|
125
|
+
end
|
126
|
+
|
127
|
+
opts.on('-g',
|
128
|
+
'--generate TOPLIST_FILE',
|
129
|
+
'Generate a user from a toplist file.') do |user|
|
130
|
+
@toplist_file = File.join(Dir.getwd, user)
|
131
|
+
end
|
132
|
+
|
133
|
+
opts.on('-o',
|
134
|
+
'--out OUT_FILE',
|
135
|
+
'The file to dump a generated user to.') do |file|
|
136
|
+
@out_file = File.join(Dir.getwd, file)
|
137
|
+
end
|
138
|
+
|
139
|
+
opts.on('-k',
|
140
|
+
'--app-key KEY',
|
141
|
+
'Path to libspotify application key.') do |key|
|
142
|
+
@spotify_appkey_file = File.join(Dir.getwd, key)
|
143
|
+
end
|
144
|
+
|
145
|
+
opts.on('-a',
|
146
|
+
'--account ACCOUNT',
|
147
|
+
'Username for a Spotify premium account.') do |account|
|
148
|
+
@spotify_account = account
|
149
|
+
end
|
150
|
+
|
151
|
+
opts.on('-w', '--password PASSWORD',
|
152
|
+
'Password for a Spotify premium account.') do |password|
|
153
|
+
@spotify_password = password
|
154
|
+
end
|
155
|
+
|
156
|
+
opts.on('-b', '--browser-ui',
|
157
|
+
'View the game through the browser instead of the console.') do |password|
|
158
|
+
@browser_ui = true
|
159
|
+
end
|
160
|
+
|
161
|
+
opts.on_tail('-h',
|
162
|
+
'--help',
|
163
|
+
'Show this message.') do
|
164
|
+
puts opts
|
165
|
+
exit
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|