monkeymusic 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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'