monkeymusic 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2VhMDg0NTUyMDU0ODUyMTQ2M2I4NGEyNzliMjExZDYyZTIzODJkMQ==
4
+ MTBjY2IwY2ZiYTBkOGU3ZWExYzM1NmRiZjU3OGE4N2NkMTY4Y2FjYw==
5
5
  data.tar.gz: !binary |-
6
- OTM5YjlmOWQ4MTNmZWIyYTJkMWQwNmMxYTNjNmY5ODg1ODY5OTI3Nw==
6
+ MDZiMDI1YjFmMmRmOWZmYjI3NDlhNzNjNjlhZWFkZTk3ZDM4ZGIxNQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YjczYTkxZDBmMDUwYzI0YTZmNDRkYmQ3YWRhNWVkMmVkNzEzM2MzMWNlYzUw
10
- MGM4N2Y5NDZiNjE2ZDYzNmEyNmI5NjM3MWJiYmYzMWM2NDEyNDFjZmIzZTYy
11
- OTQzMzRhMGFiOTJhMDMzM2FjYzhkZmExNjNlMDhhYWNlMzRmMTQ=
9
+ ZGIzYmE3NDExNGFjYzUxMmZlNzAzMTJkNDk3NjA2OTk2ZTlkNWFjZDk1OWY4
10
+ MmY4NTgxMTBlOTI2ZTIwNmUyYjk5YjE0NzIzYWViMzJiN2FjMjZjYmY3Yzhh
11
+ OTE0NDg1ZjEwMGJjMWYxY2VjYTE3OWExMDIwYjBhYjNhNzA0Yjg=
12
12
  data.tar.gz: !binary |-
13
- NDU2ODNkYTRlMDYyNzRmOTM1NTE5YWIzYzg3MDRmNDAyYzA2Njk1NDhlYTFi
14
- OWUyOWE4YWE4ZDczNzBlMDdkODM4ZjM0YmRhMGU2OGM1ZTA5NTJkZTYyYmYy
15
- MDgxN2NkNDc5ODY3NTIzMzg2ZmQ1NjYzY2VmMzRjYzVkYWFjNWE=
13
+ MDZiMTRlOGE3MWE4NGJjNGI2YWNlOTcyODM5ZDM0YjM5NzBhZmJiOWZlNWNh
14
+ ZmQ4YWVkZDI2OGE4YmNmNjM3OWM1MDE3ZjBiMmJmYTk1N2RjNWE0MTgyYjJl
15
+ ZWVmNjJlMGEyMTRlMGMwYjNkM2ZiNTMzMmI0NjE3OGJmODQxZGI=
@@ -2,5 +2,5 @@
2
2
  require File.dirname(__FILE__) + '/../lib/monkey_music'
3
3
  require File.dirname(__FILE__) + '/../lib/monkey_music_generate'
4
4
 
5
- generator = MonkeyMusic::Generator.new
6
- generator.run
5
+ runner = MonkeyMusic::Generate::Runner.new
6
+ runner.run
data/levels/bomberman2.rb CHANGED
@@ -1,20 +1,18 @@
1
1
  carrying_capacity 5
2
- metadata_requests_per_turn 2
3
- max_turns 100
2
+ turn_limit 500
3
+ time_limit 20000
4
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
- "#" => Wall,
15
- })
5
+ legend "1" => Monkey.player(1),
6
+ "2" => Monkey.player(2),
7
+ "X" => Track.worth(-2),
8
+ "x" => Track.worth(-1),
9
+ "l" => Track.worth(1),
10
+ "t" => Track.worth(2),
11
+ "T" => Track.worth(3),
12
+ "U" => User,
13
+ "#" => Wall
16
14
 
17
- layout <<LAYOUT
15
+ layout <<EOS
18
16
  Xl 1 U 2 lX
19
17
  t ll ll t
20
18
  ###t ########### t###
@@ -28,4 +26,4 @@ t ll ll t
28
26
  ### # # # # # # # ###
29
27
  #t # # # t#
30
28
  #l###l#t#t#t#t#l###l#
31
- LAYOUT
29
+ EOS
@@ -0,0 +1,23 @@
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
+ "#" => Wall,
15
+ })
16
+
17
+ layout <<LAYOUT
18
+ ....t..t...
19
+ .#.......#.
20
+ #..#1U2#..#
21
+ .#X.....X#.
22
+ .....t.....
23
+ LAYOUT
data/levels/testlevel.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  carrying_capacity 3
2
- metadata_requests_per_turn 2
3
- max_turns 100
2
+ turn_limit 100
3
+ time_limit 300
4
4
 
5
5
  legend({
6
6
  "1" => Monkey.player(1),
@@ -11,18 +11,19 @@ legend({
11
11
  "t" => Track.worth(2),
12
12
  "T" => Track.worth(3),
13
13
  "U" => User,
14
+ "W" => Wall,
14
15
  })
15
16
 
16
17
  layout <<LAYOUT
17
18
  ...........
18
- ..x........
19
- ...........
19
+ .WW.....WW.
20
+ .Wx.....xW.
20
21
  .......T...
21
22
  1..........
22
23
  ...t......U
23
24
  2..........
24
25
  .......l...
25
- ...........
26
- ..X........
26
+ .WX.....xW.
27
+ .WW.....WW.
27
28
  ...........
28
29
  LAYOUT
@@ -12,24 +12,28 @@ module MonkeyMusic
12
12
 
13
13
  def start
14
14
  @ui.update(@level)
15
- @level.max_turns.times do
16
- if @level.complete?
17
- break
18
- end
15
+ # Send initial state to players
16
+ init_threads = []
17
+ @players.each do |p|
18
+ init_threads << Thread.new { p.init! }
19
+ end
20
+ init_threads.each(&:join)
21
+ # Start the game
22
+ @level.turn_limit.times do |turn|
23
+ turn += 1
24
+ break if @level.complete?
19
25
  # Query players for moves
20
26
  query_threads = []
21
- query_time = Benchmark.realtime do
27
+ turn_time = Benchmark.realtime do
22
28
  @players.each do |p|
23
- query_threads << Thread.new do
24
- p.query_move!
25
- end
29
+ query_threads << Thread.new { p.query! turn }
26
30
  end
27
31
  query_threads.each(&:join)
28
32
  end
29
33
  # Move players in random order
30
34
  @players.shuffle.each { |p| p.move! }
31
- # Update ui
32
- @ui.update(@level, query_time)
35
+ ## Update ui
36
+ @ui.update(@level, turn, turn_time)
33
37
  end
34
38
  end
35
39
 
@@ -2,9 +2,8 @@ require 'json'
2
2
 
3
3
  module MonkeyMusic
4
4
  class Level
5
- attr_accessor :width, :height, :max_turns, :requests_per_turn
6
- attr_reader :players
7
- attr_reader :user
5
+ attr_accessor :width, :height, :turn_limit, :time_limit
6
+ attr_reader :players, :user, :units
8
7
 
9
8
  def initialize(players, user)
10
9
  @players = players
@@ -33,6 +32,10 @@ module MonkeyMusic
33
32
  (@players.detect { |p| p.monkey.carrying.count > 0 }).nil?
34
33
  end
35
34
 
35
+ def tracks
36
+ @units.select {|u| u.kind_of? Track }
37
+ end
38
+
36
39
  def remove(unit)
37
40
  @units.reject! { |u| u == unit }
38
41
  end
@@ -8,12 +8,13 @@ module MonkeyMusic
8
8
  @legend = {}
9
9
  end
10
10
 
11
- def max_turns(max_turns)
12
- @level.max_turns = max_turns
11
+ def turn_limit(turn_limit)
12
+ @level.turn_limit = turn_limit
13
13
  end
14
14
 
15
- def metadata_requests_per_turn(n)
16
- @level.requests_per_turn = n
15
+ def time_limit(time_limit)
16
+ @level.time_limit = time_limit
17
+ @level.players.each {|p| p.remaining_time = time_limit }
17
18
  end
18
19
 
19
20
  def carrying_capacity(capacity)
@@ -0,0 +1,15 @@
1
+ module MonkeyMusic::Metadata
2
+ class Album
3
+ attr_reader :name, :artist, :year
4
+
5
+ def initialize(args = {})
6
+ @name = args[:name]
7
+ @artist = args[:artist]
8
+ @year = args[:year]
9
+ end
10
+
11
+ def serialize
12
+ "#{@name},#{@artist},#{@year}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module MonkeyMusic::Metadata
2
+ class Artist
3
+ attr_accessor :name
4
+
5
+ def initialize(args = {})
6
+ @name = args[:name]
7
+ end
8
+
9
+ def serialize
10
+ @name
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ module MonkeyMusic::Metadata
2
+ class Track
3
+ attr_reader :uri, :name, :artist, :album, :year, :multiplier, :value
4
+
5
+ def initialize(args = {})
6
+ @name = args[:name]
7
+ @artist = args[:artist]
8
+ @album = args[:album]
9
+ @year = args[:year]
10
+ @uri = args[:uri]
11
+ end
12
+
13
+ def set_value(multiplier, value)
14
+ @multiplier = multiplier
15
+ @value = value
16
+ end
17
+
18
+ def serialize
19
+ "#{@name},#{@artist},#{@album},#{@year}"
20
+ end
21
+ end
22
+ end
@@ -1,42 +1,110 @@
1
+ require 'benchmark'
2
+
1
3
  module MonkeyMusic
2
4
  class Player
3
- attr_accessor :monkey, :level
5
+ attr_accessor :monkey, :level, :has_boost, :remaining_time
4
6
 
5
7
  def initialize(file)
6
8
  @file = file
7
- @monkey = Monkey.new()
9
+ @monkey = Monkey.new
10
+ @has_boost = true
11
+ @penalty = 0
12
+ @moves = []
13
+ @queries = []
14
+ end
15
+
16
+ def init!
17
+ IO.popen(@file, "r+") {|io| io.puts initial_output }
8
18
  end
9
19
 
10
- def query_move!
11
- IO.popen(@file, "r+") do |io|
12
- io.puts player_output
13
- move = io.gets
14
- @next_move = parse_move(move) if move
20
+ def query!(turn)
21
+ if @penalty > 0
22
+ @penalty -= 1
23
+ @remaining_time = @monkey.level.time_limit if @penalty < 1
24
+ else
25
+ IO.popen(@file, "r+") do |io|
26
+ io.puts turn_output(turn)
27
+ @remaining_time -= (Benchmark.realtime { @input = io.gets } * 1000).round
28
+ parse!(@input) if @input
29
+ io.puts response_to(@queries) unless @queries.empty?
30
+ @queries = []
31
+ end
32
+ @penalty = 5 if @remaining_time < 0
15
33
  end
16
34
  end
17
35
 
18
- def player_output
19
- [ @monkey.id,
36
+ def initial_output
37
+ level = @monkey.level
38
+ user = @monkey.level.user
39
+ [ "INIT",
40
+ @monkey.id,
41
+ level.width,
42
+ level.height,
43
+ level.turn_limit,
44
+ user.toplists[:top_tracks].length,
45
+ user.toplists[:top_tracks].map(&:serialize).join("\n"),
46
+ user.toplists[:top_albums].length,
47
+ user.toplists[:top_albums].map(&:serialize).join("\n"),
48
+ user.toplists[:top_artists].length,
49
+ user.toplists[:top_artists].map(&:serialize).join("\n"),
50
+ user.toplists[:disliked_artists].length,
51
+ user.toplists[:disliked_artists].map(&:serialize).join("\n"),
52
+ ].join("\n")
53
+ end
54
+
55
+ def turn_output(turn)
56
+ [ "TURN",
57
+ turn,
20
58
  @monkey.remaining_capacity,
21
- @monkey.level.requests_per_turn,
22
- @monkey.level.width,
23
- @monkey.level.height,
59
+ @remaining_time,
24
60
  @monkey.level.serialize,
25
61
  ].join("\n")
26
62
  end
27
63
 
28
- def parse_move(s)
29
- case s.chomp
30
- when "N" then :north
31
- when "W" then :west
32
- when "E" then :east
33
- when "S" then :south
64
+ def parse!(s)
65
+ @tokens = s.chomp.split(",")
66
+ parse_next_token!
67
+ end
68
+
69
+ def parse_next_token!
70
+ token = @tokens.shift
71
+ if /^[NWES]$/.match(token) then @moves << parse_move(token)
72
+ elsif /^spotify:track:/.match(token) then @queries << token
73
+ elsif "B" == token then boost!
74
+ end
75
+ end
76
+
77
+ def boost!
78
+ return unless @has_boost
79
+ @has_boost = false
80
+ [3, @tokens.length].min.times { parse_next_token! }
81
+ end
82
+
83
+ def response_to(queries)
84
+ tracks = []
85
+ queries.each do |uri|
86
+ tracks << @monkey.level.tracks.find {|t| t.uri == uri }
87
+ end
88
+ lines = []
89
+ lines << tracks.length
90
+ tracks.each do |track|
91
+ lines << "#{track.uri},#{track.metadata.serialize}"
92
+ end
93
+ lines.join("\n")
94
+ end
95
+
96
+ def parse_move(move)
97
+ case move
98
+ when "N" then :north
99
+ when "W" then :west
100
+ when "E" then :east
101
+ when "S" then :south
34
102
  end
35
103
  end
36
104
 
37
105
  def move!
38
- @monkey.move! @next_move if @next_move
39
- @next_move = nil
106
+ @moves.each {|move| @monkey.move! move }
107
+ @moves = []
40
108
  end
41
109
 
42
110
  def to_s
@@ -3,7 +3,7 @@ require 'optparse'
3
3
  module MonkeyMusic
4
4
  class Runner
5
5
 
6
- @@default_level = 'testlevel.rb'
6
+ @@default_level = 'bomberman2.rb'
7
7
  @@default_user = 'synth.yaml'
8
8
 
9
9
  def initialize(arguments)
@@ -43,9 +43,9 @@ module MonkeyMusic
43
43
  print "Using browser UI. Press the enter key to start game. "
44
44
  gets
45
45
  puts "Starting game..."
46
- ui = BrowserUI.new(@delay)
46
+ ui = UI::Browser.new(@delay)
47
47
  else
48
- ui = ConsoleUI.new(@delay)
48
+ ui = UI::Console.new(@delay)
49
49
  end
50
50
  ## Start game
51
51
  @game = Game.new(level, @players, ui)
@@ -97,14 +97,14 @@ module MonkeyMusic
97
97
  @delay = delay
98
98
  end
99
99
 
100
- opts.on('-b', '--browser-ui',
101
- 'View the game through the browser instead of the console.') do |password|
102
- @browser_ui = true
103
- end
100
+ #opts.on('-b', '--browser-ui',
101
+ #'View the game through the browser instead of the console.') do |password|
102
+ #@browser_ui = true
103
+ #end
104
104
 
105
105
  opts.on('-v', '--version',
106
106
  'Show the current version.') do |password|
107
- puts '0.0.3' # TODO: Find out how to extract version from GemSpec
107
+ puts '0.0.5' # TODO: Find out how to extract version from GemSpec
108
108
  exit
109
109
  end
110
110
 
@@ -1,12 +1,11 @@
1
1
  require 'em-websocket'
2
2
  require 'json'
3
- require 'rack'
4
3
 
5
- module MonkeyMusic
6
- class BrowserUI
4
+ module MonkeyMusic::UI
5
+ class Browser
7
6
 
8
- def initialize(delay)
9
- @delay = delay || 1
7
+ def initialize(delay = 1)
8
+ @delay = delay
10
9
  puts "Initializing websockets..."
11
10
  Thread.new {
12
11
  EM.run {
@@ -27,9 +26,9 @@ module MonkeyMusic
27
26
  puts "Websockets initialized!"
28
27
  end
29
28
 
30
- def update(level)
29
+ def update(level, query_time = 0)
31
30
  @ws.send(level.as_json) if @ws
32
- sleep @delay
31
+ sleep 1
33
32
  end
34
33
 
35
34
  end
@@ -1,5 +1,5 @@
1
- module MonkeyMusic
2
- class ConsoleUI
1
+ module MonkeyMusic::UI
2
+ class Console
3
3
 
4
4
  def initialize(delay)
5
5
  @delay = delay || 1
@@ -12,7 +12,7 @@ module MonkeyMusic
12
12
  puts "\n"*5
13
13
  end
14
14
 
15
- def update(level, query_time = 0)
15
+ def update(level, turn = 0, query_time = 0)
16
16
  # Clear screen
17
17
  puts "\e[H\e[2J"
18
18
  # Level
@@ -21,9 +21,10 @@ module MonkeyMusic
21
21
  puts "\n"
22
22
  level.players.each do |player|
23
23
  monkey = player.monkey
24
- puts "---"
24
+ puts "--- Turn: #{turn}/#{level.turn_limit} ---"
25
25
  print "#{monkey.name} | "
26
26
  print "Score: #{monkey.score} | "
27
+ print "Time: #{player.remaining_time} | "
27
28
  puts "Capacity: #{monkey.remaining_capacity}"
28
29
  monkey.carrying.each { |t| puts "#{t.value}p: #{t.name}" }
29
30
  print("\n"*monkey.remaining_capacity)
@@ -1,22 +1,32 @@
1
1
  module MonkeyMusic
2
2
  class Track < Base
3
- attr_accessor :uri, :name, :artist, :album, :popularity, :year,
4
- :value, :multiplier
3
+ attr_accessor :metadata
5
4
 
6
5
  def self.worth(n)
7
6
  Class.new Track do @worth = n end
8
7
  end
9
8
 
10
9
  def self.from_user(user)
11
- if @worth
10
+ track = Track.new
11
+ track.metadata = if @worth
12
12
  user.recommend!(@worth) || user.recommendations.sample
13
13
  else
14
14
  user.recommendations.sample
15
15
  end
16
+ track
17
+ end
18
+
19
+ # Delegate to metadata
20
+ def method_missing(method, *args, &block)
21
+ if @metadata.respond_to?(method)
22
+ @metadata.send(method, *args, &block)
23
+ else
24
+ raise NoMethodError
25
+ end
16
26
  end
17
27
 
18
28
  def serialize
19
- @uri
29
+ @metadata.uri
20
30
  end
21
31
 
22
32
  def to_json(options = {})
@@ -24,9 +34,9 @@ module MonkeyMusic
24
34
  :x => @x,
25
35
  :y => @y,
26
36
  :type => self.class.name.split('::').last,
27
- :name => @name,
28
- :multiplier => @multiplier,
29
- :value => @value,
37
+ :name => @metadata.name,
38
+ :multiplier => @metadata.multiplier,
39
+ :value => @metadata.value,
30
40
  }.to_json
31
41
  end
32
42
  end
@@ -21,14 +21,12 @@ module MonkeyMusic
21
21
  end
22
22
 
23
23
  def dump
24
- YAML::dump({
25
- :toplists => @toplists,
26
- :recommendations => @recommendations
27
- })
24
+ YAML::dump :toplists => @toplists,
25
+ :recommendations => @recommendations
28
26
  end
29
27
 
30
28
  def load_from_file(file)
31
- data = YAML::load(IO.read(file))
29
+ data = YAML::load(IO.read file)
32
30
  @toplists = data[:toplists]
33
31
  @recommendations = data[:recommendations]
34
32
  @remaining_recommendations = @recommendations
data/lib/monkey_music.rb CHANGED
@@ -8,8 +8,12 @@ require 'monkey_music/player'
8
8
  require 'monkey_music/level'
9
9
  require 'monkey_music/level_loader'
10
10
 
11
- require 'monkey_music/ui/console_ui'
12
- require 'monkey_music/ui/browser_ui'
11
+ require 'monkey_music/ui/console'
12
+ require 'monkey_music/ui/browser'
13
+
14
+ require 'monkey_music/metadata/track'
15
+ require 'monkey_music/metadata/album'
16
+ require 'monkey_music/metadata/artist'
13
17
 
14
18
  require 'monkey_music/units/base'
15
19
  require 'monkey_music/units/monkey'