monkeymusic 0.0.14 → 0.1.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.
- checksums.yaml +8 -8
- data/Gemfile +0 -1
- data/README.md +166 -177
- data/demo_players/java/DemoPlayer.java +250 -0
- data/demo_players/java/install +2 -0
- data/demo_players/java/runme +2 -0
- data/demo_players/python/install +2 -0
- data/demo_players/python/monkey.py +111 -0
- data/demo_players/python/runme +2 -0
- data/demo_players/python/state.pickle +0 -0
- data/demo_players/python/util.py +29 -0
- data/demo_players/python/util.pyc +0 -0
- data/{demo_player → demo_players/ruby/demo_player.rb} +3 -2
- data/levels/demo_level.rb +1 -0
- data/levels/maze.rb +20 -0
- data/levels/metadata.rb +17 -0
- data/levels/walls.rb +20 -0
- data/lib/monkey_music/game.rb +1 -2
- data/lib/monkey_music/level.rb +2 -9
- data/lib/monkey_music/level_loader.rb +4 -0
- data/lib/monkey_music/player.rb +8 -6
- data/lib/monkey_music/runner.rb +15 -12
- data/lib/monkey_music/ui/browser.rb +26 -17
- data/lib/monkey_music/ui/console.rb +13 -15
- data/lib/monkey_music_generate/runner.rb +2 -3
- data/lib/monkey_music_generate/score_system.rb +2 -0
- data/users/demo_user.yaml +250 -250
- metadata +15 -11
- data/levels/testlevel.rb +0 -29
- data/levels/testlevel_maze.rb +0 -24
- data/levels/testmaze_10.rb +0 -38
- data/levels/testmaze_20.rb +0 -38
- data/levels/testmaze_30.rb +0 -38
- data/levels/the_last_crusade.rb +0 -21
- data/levels/travelling_salesmonkeys.rb +0 -0
- data/users/synth.rb +0 -11
@@ -0,0 +1,250 @@
|
|
1
|
+
import java.util.Set;
|
2
|
+
import java.util.List;
|
3
|
+
import java.util.Map;
|
4
|
+
import java.util.HashSet;
|
5
|
+
import java.util.HashMap;
|
6
|
+
import java.util.ArrayList;
|
7
|
+
import java.util.Scanner;
|
8
|
+
import java.io.Serializable;
|
9
|
+
import java.io.ObjectOutputStream;
|
10
|
+
import java.io.FileOutputStream;
|
11
|
+
import java.io.ObjectInputStream;
|
12
|
+
import java.io.FileInputStream;
|
13
|
+
|
14
|
+
public class DemoPlayer {
|
15
|
+
public static void main(String[] args) throws Exception {
|
16
|
+
Scanner sc = new Scanner(System.in);
|
17
|
+
String roundType = sc.nextLine();
|
18
|
+
String id = sc.nextLine();
|
19
|
+
Monkey monkey;
|
20
|
+
if (roundType.equals("INIT")) {
|
21
|
+
monkey = new Monkey(id);
|
22
|
+
monkey.init(sc);
|
23
|
+
} else {
|
24
|
+
monkey = Monkey.readFromCache(id);
|
25
|
+
monkey.turn(sc);
|
26
|
+
}
|
27
|
+
sc.close();
|
28
|
+
monkey.writeToCache();
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
class Monkey implements Serializable {
|
33
|
+
public static final long serialVersionUID = 0;
|
34
|
+
|
35
|
+
static final String CACHE_PREFIX = "cache_";
|
36
|
+
|
37
|
+
final String id;
|
38
|
+
// Position
|
39
|
+
int x, y;
|
40
|
+
// Toplists
|
41
|
+
int topDecade;
|
42
|
+
Set<String> topTracks = new HashSet<String>(),
|
43
|
+
topAlbums = new HashSet<String>(),
|
44
|
+
topArtists = new HashSet<String>(),
|
45
|
+
dislikedArtists = new HashSet<String>();
|
46
|
+
// URI dictionary
|
47
|
+
Map<String, Track> knownURIs = new HashMap<String, Track>();
|
48
|
+
// Tracks
|
49
|
+
List<Track> unknownTracks;
|
50
|
+
List<Track> knownTracks;
|
51
|
+
int turn, turnLimit;
|
52
|
+
int width, height;
|
53
|
+
int remainingCapacity, remainingExecutionTime, boostCooldown;
|
54
|
+
String[][] level;
|
55
|
+
|
56
|
+
Monkey(String id) {
|
57
|
+
this.id = id;
|
58
|
+
}
|
59
|
+
|
60
|
+
void init(Scanner sc) {
|
61
|
+
parseInit(sc);
|
62
|
+
parseToplists(sc);
|
63
|
+
}
|
64
|
+
|
65
|
+
void turn(Scanner sc) {
|
66
|
+
parseTurn(sc);
|
67
|
+
parseMetadata(sc);
|
68
|
+
parseLevel(sc);
|
69
|
+
}
|
70
|
+
|
71
|
+
void parseInit(Scanner sc) {
|
72
|
+
width = sc.nextInt();
|
73
|
+
height = sc.nextInt();
|
74
|
+
turnLimit = sc.nextInt();
|
75
|
+
level = new String[width][height];
|
76
|
+
}
|
77
|
+
|
78
|
+
void parseToplists(Scanner sc) {
|
79
|
+
List<Integer> decades = new ArrayList<Integer>();
|
80
|
+
// Top tracks
|
81
|
+
int numTracks = sc.nextInt();
|
82
|
+
sc.nextLine();
|
83
|
+
for (int i = 0; i < numTracks; i++) {
|
84
|
+
String entry = sc.nextLine();
|
85
|
+
// 0:[track],1:[album],2:[artist],3:[year]
|
86
|
+
String[] parts = entry.split(",");
|
87
|
+
topTracks.add(parts[0]);
|
88
|
+
int decade = Util.toDecade(Integer.parseInt(parts[3]));
|
89
|
+
decades.add(decade);
|
90
|
+
}
|
91
|
+
// Top albums
|
92
|
+
int numAlbums = sc.nextInt();
|
93
|
+
sc.nextLine();
|
94
|
+
for (int i = 0; i < numAlbums; i++) {
|
95
|
+
String entry = sc.nextLine();
|
96
|
+
// 0:[album],1:[artist],2:[year]
|
97
|
+
String[] parts = entry.split(",");
|
98
|
+
topAlbums.add(parts[0]);
|
99
|
+
int decade = Util.toDecade(Integer.parseInt(parts[2]));
|
100
|
+
decades.add(decade);
|
101
|
+
}
|
102
|
+
// Top decade
|
103
|
+
topDecade = Util.getPopularElement(
|
104
|
+
decades.toArray(new Integer[decades.size()]));
|
105
|
+
// Top artists
|
106
|
+
int numArtists = sc.nextInt();
|
107
|
+
sc.nextLine();
|
108
|
+
for (int i = 0; i < numArtists; i++) {
|
109
|
+
// 0:[artist]
|
110
|
+
String entry = sc.nextLine();
|
111
|
+
topArtists.add(entry);
|
112
|
+
}
|
113
|
+
// Disliked artists
|
114
|
+
int numDislikedArtists = sc.nextInt();
|
115
|
+
sc.nextLine();
|
116
|
+
for (int i = 0; i < numDislikedArtists; i++) {
|
117
|
+
// 0:[artist]
|
118
|
+
String entry = sc.nextLine();
|
119
|
+
dislikedArtists.add(entry);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
void parseTurn(Scanner sc) {
|
124
|
+
turn = sc.nextInt();
|
125
|
+
remainingCapacity = sc.nextInt();
|
126
|
+
remainingExecutionTime = sc.nextInt();
|
127
|
+
boostCooldown = sc.nextInt();
|
128
|
+
}
|
129
|
+
|
130
|
+
void parseMetadata(Scanner sc) {
|
131
|
+
int numResults = sc.nextInt();
|
132
|
+
sc.nextLine();
|
133
|
+
for (int i = 0; i < numResults; i++) {
|
134
|
+
String metadata = sc.nextLine();
|
135
|
+
Track knownTrack = Track.fromMetadata(metadata);
|
136
|
+
// 0:[uri],1:[[track],[album],[artist],[year]]
|
137
|
+
String[] parts = metadata.split(",", 1);
|
138
|
+
knownURIs.put(parts[0], knownTrack);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
void parseLevel(Scanner sc) {
|
143
|
+
unknownTracks = new ArrayList<Track>();
|
144
|
+
knownTracks = new ArrayList<Track>();
|
145
|
+
for (int y = 0; y < height; y++) {
|
146
|
+
String row = sc.nextLine();
|
147
|
+
String[] cells = row.split(",");
|
148
|
+
for (int x = 0; x < width; x++) {
|
149
|
+
level[x][y] = cells[x];
|
150
|
+
if (Util.isURI(cells[x])) {
|
151
|
+
String uri = cells[x];
|
152
|
+
if (!knownURIs.containsKey(uri)) {
|
153
|
+
unknownTracks.add(new Track(uri).place(x, y));
|
154
|
+
} else {
|
155
|
+
knownTracks.add(knownURIs.get(uri).copy().place(x, y));
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
void writeToCache() throws Exception {
|
163
|
+
ObjectOutputStream out =
|
164
|
+
new ObjectOutputStream(new FileOutputStream(CACHE_PREFIX + id));
|
165
|
+
out.writeObject(this);
|
166
|
+
out.close();
|
167
|
+
}
|
168
|
+
|
169
|
+
static Monkey readFromCache(String id) throws Exception {
|
170
|
+
ObjectInputStream in =
|
171
|
+
new ObjectInputStream(new FileInputStream(CACHE_PREFIX + id));
|
172
|
+
Monkey monkey = (Monkey) in.readObject();
|
173
|
+
in.close();
|
174
|
+
return monkey;
|
175
|
+
}
|
176
|
+
|
177
|
+
}
|
178
|
+
|
179
|
+
class Track implements Cloneable, Serializable {
|
180
|
+
public static final long serialVersionUID = 0;
|
181
|
+
|
182
|
+
String uri, name, album, artist, year;
|
183
|
+
int x, y;
|
184
|
+
int value;
|
185
|
+
|
186
|
+
Track (String uri) {
|
187
|
+
this.uri = uri;
|
188
|
+
}
|
189
|
+
|
190
|
+
static Track fromMetadata(String metadata) {
|
191
|
+
// 0:[uri],1:[name],2:[album],3:[artist],4:[year]
|
192
|
+
String[] parts = metadata.split(",");
|
193
|
+
Track track = new Track(parts[0]);
|
194
|
+
track.name = parts[1];
|
195
|
+
track.album = parts[2];
|
196
|
+
track.artist = parts[3];
|
197
|
+
track.year = parts[4];
|
198
|
+
return track;
|
199
|
+
}
|
200
|
+
|
201
|
+
Track place(int x, int y) {
|
202
|
+
this.x = x;
|
203
|
+
this.y = y;
|
204
|
+
return this;
|
205
|
+
}
|
206
|
+
|
207
|
+
Track copy() {
|
208
|
+
Track copy = new Track(uri);
|
209
|
+
copy.name = name;
|
210
|
+
copy.album = album;
|
211
|
+
copy.artist = artist;
|
212
|
+
copy.year = year;
|
213
|
+
copy.value = value;
|
214
|
+
return copy;
|
215
|
+
}
|
216
|
+
|
217
|
+
@Override public int hashCode() { return uri.hashCode(); }
|
218
|
+
}
|
219
|
+
|
220
|
+
class Util {
|
221
|
+
/**
|
222
|
+
* http://stackoverflow.com/questions/8545590/java-find-the-most-popular-element-in-int-array
|
223
|
+
*/
|
224
|
+
static int getPopularElement(Integer[] a) {
|
225
|
+
int count = 1, tempCount;
|
226
|
+
int popular = a[0];
|
227
|
+
int temp = 0;
|
228
|
+
for (int i = 0; i < (a.length - 1); i++) {
|
229
|
+
temp = a[i];
|
230
|
+
tempCount = 0;
|
231
|
+
for (int j = 1; j < a.length; j++) {
|
232
|
+
if (temp == a[j])
|
233
|
+
tempCount++;
|
234
|
+
}
|
235
|
+
if (tempCount > count) {
|
236
|
+
popular = temp;
|
237
|
+
count = tempCount;
|
238
|
+
}
|
239
|
+
}
|
240
|
+
return popular;
|
241
|
+
}
|
242
|
+
|
243
|
+
static int toDecade(int year) {
|
244
|
+
return (year % 100) / 10;
|
245
|
+
}
|
246
|
+
|
247
|
+
static boolean isURI(String s) {
|
248
|
+
return s.length() == 36 && s.substring(0, 14).equals("spotify:track:");
|
249
|
+
}
|
250
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import logging
|
2
|
+
import os.path
|
3
|
+
import pickle
|
4
|
+
import sys
|
5
|
+
|
6
|
+
import util
|
7
|
+
|
8
|
+
STATE_FILENAME = 'state.pickle'
|
9
|
+
TRACK_URI_HEADER = 'spotify:track:'
|
10
|
+
|
11
|
+
class Monkey(object):
|
12
|
+
def __init__(self):
|
13
|
+
self._id = 0
|
14
|
+
self._w = 0
|
15
|
+
self._h = 0
|
16
|
+
self._turn_limit = 0
|
17
|
+
self._turn = 0
|
18
|
+
self._capacity = 0
|
19
|
+
self._time_left = 0
|
20
|
+
self._top_tracks = None
|
21
|
+
self._top_albums = None
|
22
|
+
self._top_artists = None
|
23
|
+
self._bad_artists = None
|
24
|
+
self._bad_tracks = set()
|
25
|
+
self._map = {}
|
26
|
+
self._pos = None
|
27
|
+
self._user = None
|
28
|
+
self._boost_cooldown = 0
|
29
|
+
self._track_pos = {} # pos -> uri
|
30
|
+
self._metadata = {} # uri -> metadata
|
31
|
+
self._objective = None
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def process_input(cls, stream):
|
35
|
+
monkey = None
|
36
|
+
line = stream.readline().strip()
|
37
|
+
if line == 'INIT':
|
38
|
+
logging.basicConfig(filename='monkey.log', filemode='w', level=logging.DEBUG)
|
39
|
+
monkey = cls()
|
40
|
+
monkey.initialize(stream)
|
41
|
+
else:
|
42
|
+
logging.basicConfig(filename='monkey.log', filemode='a', level=logging.DEBUG)
|
43
|
+
monkey = cls.load()
|
44
|
+
monkey.update(stream)
|
45
|
+
return monkey
|
46
|
+
|
47
|
+
def initialize(self, stream):
|
48
|
+
self._id = stream.readline().strip()
|
49
|
+
self._w = util.get_int(stream)
|
50
|
+
self._h = util.get_int(stream)
|
51
|
+
self._turn_limit = util.get_int(stream)
|
52
|
+
self._top_tracks = util.get_set(stream)
|
53
|
+
self._top_albums = util.get_set(stream)
|
54
|
+
self._top_artists = util.get_set(stream)
|
55
|
+
self._bad_artists = util.get_set(stream)
|
56
|
+
|
57
|
+
def update(self, stream):
|
58
|
+
self._id = stream.readline().strip()
|
59
|
+
self._turn = util.get_int(stream)
|
60
|
+
self._capacity = util.get_int(stream)
|
61
|
+
self._time_left = util.get_int(stream)
|
62
|
+
self._boost_cooldown = util.get_int(stream)
|
63
|
+
self._track_pos = {}
|
64
|
+
self.browse_result(sys.stdin)
|
65
|
+
for y in xrange(self._h):
|
66
|
+
line = stream.readline().strip()
|
67
|
+
for x, square in enumerate(line.split(',')):
|
68
|
+
|
69
|
+
self._map[x, y] = square
|
70
|
+
if square == self._id:
|
71
|
+
self._pos = (x, y)
|
72
|
+
elif square == 'U':
|
73
|
+
self._user = (x, y)
|
74
|
+
elif square.startswith(TRACK_URI_HEADER):
|
75
|
+
self._track_pos[x, y] = square
|
76
|
+
try:
|
77
|
+
metadata = self._metadata[square]
|
78
|
+
self._map[x, y] = '+' if self.track_value(metadata) > 0 else '-'
|
79
|
+
except KeyError:
|
80
|
+
self._map[x, y] = '?'
|
81
|
+
|
82
|
+
def action(self):
|
83
|
+
if self._turn >= 1:
|
84
|
+
print 'W'
|
85
|
+
|
86
|
+
def browse_result(self, stream):
|
87
|
+
browsed_tracks = util.get_set(sys.stdin)
|
88
|
+
for track in browsed_tracks:
|
89
|
+
logging.debug('[%d] Browsed track: %s', self._turn, track)
|
90
|
+
uri, metadata = track.split(',', 1)
|
91
|
+
self._metadata[uri] = metadata
|
92
|
+
|
93
|
+
def save(self):
|
94
|
+
with open(self.save_path(), 'wb') as f:
|
95
|
+
pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
|
96
|
+
|
97
|
+
@classmethod
|
98
|
+
def load(cls):
|
99
|
+
with open(cls.save_path(), 'rb') as f:
|
100
|
+
return pickle.load(f)
|
101
|
+
|
102
|
+
@classmethod
|
103
|
+
def save_path(cls):
|
104
|
+
dir_path = os.path.dirname(__file__)
|
105
|
+
return os.path.join(dir_path, STATE_FILENAME)
|
106
|
+
|
107
|
+
if __name__ == '__main__':
|
108
|
+
monkey = Monkey.process_input(sys.stdin)
|
109
|
+
monkey.action()
|
110
|
+
monkey.save()
|
111
|
+
sys.stdout.flush()
|
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
INTEGER = re.compile(r'(\d+).*')
|
4
|
+
|
5
|
+
D_POS = {'W': (-1, 0), 'N': (0, -1), 'E': (1, 0), 'S': (0, 1)}
|
6
|
+
MOVES = dict([(v, k) for k, v in D_POS.iteritems()])
|
7
|
+
|
8
|
+
def distance(p0, p1):
|
9
|
+
return abs(p0[0] - p1[0]) + abs(p0[1] - p1[1])
|
10
|
+
|
11
|
+
def move(p_from, p_to):
|
12
|
+
dx = p_to[0] - p_from[0]
|
13
|
+
dy = p_to[1] - p_from[1]
|
14
|
+
return MOVES[dx, dy]
|
15
|
+
|
16
|
+
def follow_path(self, path):
|
17
|
+
return move(path[0], path[1])
|
18
|
+
|
19
|
+
def get_int(stream):
|
20
|
+
line = stream.readline().strip()
|
21
|
+
match = INTEGER.match(line)
|
22
|
+
return int(match.group(1))
|
23
|
+
|
24
|
+
def get_set(stream):
|
25
|
+
s = set()
|
26
|
+
size = get_int(stream)
|
27
|
+
for ix in xrange(size):
|
28
|
+
s.add(stream.readline().strip())
|
29
|
+
return s
|
Binary file
|
@@ -61,12 +61,13 @@ class DemoPlayer
|
|
61
61
|
@turn = Integer($stdin.gets.chomp)
|
62
62
|
@remaining_capacity = Integer($stdin.gets.chomp)
|
63
63
|
@remaining_time = Integer($stdin.gets.chomp)
|
64
|
+
@boost_cooldown = Integer($stdin.gets.chomp)
|
64
65
|
# Read metadata query responses
|
65
66
|
num_responses = Integer($stdin.gets.chomp)
|
66
67
|
num_responses.times do
|
67
68
|
response = $stdin.gets.chomp.split(",")
|
68
69
|
uri = response.unshift
|
69
|
-
@known_tracks[uri]
|
70
|
+
@known_tracks[uri] = response
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
@@ -76,7 +77,7 @@ class DemoPlayer
|
|
76
77
|
row = $stdin.gets.chomp.split(',')
|
77
78
|
@width.times do |x|
|
78
79
|
case row[x]
|
79
|
-
when
|
80
|
+
when @id then @x, @y = x, y
|
80
81
|
when /spotify:track/ then @track_positions << [x, y]
|
81
82
|
when "U" then @user_position = [x, y]
|
82
83
|
end
|