berlin-ai 0.0.38 → 0.0.39
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/{CHANGELOG → CHANGELOG.md} +0 -0
- data/README.md +4 -3
- data/berlin-ai.gemspec +2 -0
- data/lib/ai/fake.rb +239 -111
- data/lib/berlin-ai.rb +8 -4
- data/lib/version.rb +1 -1
- metadata +26 -11
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NTM4MTYxM2FlOTM2YTNlMDljNTlkYTk3MmNkOGQ1Zjg1ZGExOGNlZA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 22c28ef7a0470b58c71d71b9947975d10c34556e
|
4
|
+
data.tar.gz: ab75d7229925952f3cc9fcf18770af8108b72478
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDdhY2I5ZWY0MDZlMTQ3NzE3MzM3ZWY1Y2FmNDhlM2E4MjFhZTNiMTJjN2My
|
11
|
-
ZjAxYmU5NWM0ZWVmOTg3OTQyN2IyMmQ0NTQ5NmFhNDFiZmY1ZTU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MTNmYjljODRkODA5OTdkOGI1NTFlNTE0NjAwZjhhMDc5YzhkMzNiMWI1NGY0
|
14
|
-
MjZmZmRhZmE2MThkZWRkNzg1N2FmYzEyYTI3OWNiMDIzZDk0MmE3NTIwNThj
|
15
|
-
MGQyYzBlYjFhZjExZjNjYjQ5ZTFlNGFmYmFmYTY3MWU5NDNlMjM=
|
6
|
+
metadata.gz: 329a5d53d06b5bfb5b3e5af766c8650161826321dc3be37d63f6c5bc8ed5511ae7a640024deb386112af6136a62ddba1dc2ea335267a6b895e06d5b5ffa1a39d
|
7
|
+
data.tar.gz: 19b00836e5aadc401afe1b1f2b4aae3bace1493522776bf70cb791bc2ca56919881cca51b08bc5187778fc55033c6a06362baae304394c3853a45d467ca818cc
|
data/{CHANGELOG → CHANGELOG.md}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Berlin-Ai is a gem to quickly ramp up on the [Berlin](http://www.berlin-ai.com)
|
|
4
4
|
|
5
5
|
## Changelog
|
6
6
|
|
7
|
-
[See changelog for recent changes](https://github.com/thirdside/berlin-ai/blob/master/
|
7
|
+
[See changelog for recent changes](https://github.com/thirdside/berlin-ai/blob/master/CHANGELOG.md)
|
8
8
|
|
9
9
|
## Usage
|
10
10
|
|
@@ -90,9 +90,10 @@ node.available_soldiers # Owned remaining soldiers on this node (result fr
|
|
90
90
|
node.==(other) # Check if two nodes are the same.
|
91
91
|
node.adjacent?(other_node) # Check if two nodes are adjacents.
|
92
92
|
node.occupied? # Check if some soldiers are on the node.
|
93
|
-
node.
|
94
|
-
node.mine?
|
93
|
+
node.enemy? # Check if another player (not you) owns the node.
|
94
|
+
node.mine? (node.owned?) # Check if you own the node.
|
95
95
|
node.free? # Check if no one own the node.
|
96
|
+
node.foreign? # Check if you don't own the node. Might belongs to an enemy or be free.
|
96
97
|
node.owned_by?(player_id) # Check if the node is owned by a given player.
|
97
98
|
node.adjacent_nodes # Get a list of adjacent nodes.
|
98
99
|
node.adjacent_nodes_and_self # Get a list of adjacent nodes, including this node.
|
data/berlin-ai.gemspec
CHANGED
@@ -15,11 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
16
|
s.summary = "Berlin Artificial Intelligence"
|
17
17
|
s.description = "Berlin Artificial Intelligence"
|
18
|
+
s.license = "copyleft"
|
18
19
|
|
19
20
|
s.add_dependency 'sinatra', '1.4.3'
|
20
21
|
s.add_dependency 'yajl-ruby', '1.1.0'
|
21
22
|
s.add_dependency 'sinatra-contrib', '1.4.1'
|
22
23
|
s.add_dependency 'rainbow', '~>1.1.4'
|
24
|
+
s.add_dependency 'ruby-terminfo'
|
23
25
|
s.add_dependency 'thin', '1.5.1'
|
24
26
|
|
25
27
|
s.add_development_dependency 'minitest'
|
data/lib/ai/fake.rb
CHANGED
@@ -1,39 +1,100 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
1
3
|
require 'rainbow'
|
4
|
+
require 'terminfo'
|
2
5
|
|
3
6
|
module Berlin
|
4
7
|
module Fake
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
CITY_WALL = "\u2588"
|
10
|
+
NODE_WALL = "#"
|
11
|
+
PATH = "."
|
8
12
|
|
13
|
+
MAP_DEFINITION = {
|
9
14
|
"types" => [
|
10
|
-
{"name" => "
|
11
|
-
{"name" => "
|
15
|
+
{"name" => "city","soldiers_per_turn" => 1,"points" => 1},
|
16
|
+
{"name" => "node","soldiers_per_turn" => 0,"points" => 0}
|
12
17
|
],
|
13
|
-
|
14
18
|
"nodes" => [
|
15
|
-
{"id" => 1, "type" => "city"},
|
16
|
-
{"id" => 2, "type" => "
|
17
|
-
{"id" => 3, "type" => "city"},
|
18
|
-
{"id" => 4, "type" => "
|
19
|
-
{"id" => 5, "type" => "
|
20
|
-
{"id" => 6, "type" => "city"},
|
21
|
-
{"id" => 7, "type" => "
|
22
|
-
{"id" => 8, "type" => "city"}
|
19
|
+
{"id" => 1, "type" => "city", "x" => 10, "y" => 10},
|
20
|
+
{"id" => 2, "type" => "city", "x" => 30, "y" => 10},
|
21
|
+
{"id" => 3, "type" => "city", "x" => 10, "y" => 30},
|
22
|
+
{"id" => 4, "type" => "city", "x" => 30, "y" => 30},
|
23
|
+
{"id" => 5, "type" => "city", "x" => 90, "y" => 10},
|
24
|
+
{"id" => 6, "type" => "city", "x" => 70, "y" => 10},
|
25
|
+
{"id" => 7, "type" => "city", "x" => 90, "y" => 30},
|
26
|
+
{"id" => 8, "type" => "city", "x" => 70, "y" => 30},
|
27
|
+
{"id" => 9, "type" => "city", "x" => 10, "y" => 90},
|
28
|
+
{"id" => 10, "type" => "city", "x" => 10, "y" => 70},
|
29
|
+
{"id" => 11, "type" => "city", "x" => 30, "y" => 90},
|
30
|
+
{"id" => 12, "type" => "city", "x" => 30, "y" => 70},
|
31
|
+
{"id" => 13, "type" => "city", "x" => 90, "y" => 90},
|
32
|
+
{"id" => 14, "type" => "city", "x" => 70, "y" => 90},
|
33
|
+
{"id" => 15, "type" => "city", "x" => 90, "y" => 70},
|
34
|
+
{"id" => 16, "type" => "city", "x" => 70, "y" => 70},
|
35
|
+
{"id" => 17, "type" => "node", "x" => 25, "y" => 50},
|
36
|
+
{"id" => 18, "type" => "node", "x" => 75, "y" => 50},
|
37
|
+
{"id" => 19, "type" => "node", "x" => 40, "y" => 50},
|
38
|
+
{"id" => 20, "type" => "node", "x" => 60, "y" => 50},
|
39
|
+
{"id" => 21, "type" => "node", "x" => 50, "y" => 25},
|
40
|
+
{"id" => 22, "type" => "node", "x" => 50, "y" => 75},
|
41
|
+
{"id" => 23, "type" => "node", "x" => 50, "y" => 40},
|
42
|
+
{"id" => 24, "type" => "node", "x" => 50, "y" => 60}
|
23
43
|
],
|
24
|
-
|
25
|
-
"paths" => [
|
44
|
+
"paths"=> [
|
26
45
|
{"from" => 1, "to" => 2},
|
46
|
+
{"from" => 1, "to" => 3},
|
27
47
|
{"from" => 2, "to" => 3},
|
28
|
-
{"from" => 2, "to" =>
|
29
|
-
{"from" => 3, "to" =>
|
30
|
-
{"from" => 5, "to" =>
|
31
|
-
{"from" =>
|
32
|
-
{"from" => 7, "to" => 4},
|
48
|
+
{"from" => 2, "to" => 4},
|
49
|
+
{"from" => 3, "to" => 4},
|
50
|
+
{"from" => 5, "to" => 6},
|
51
|
+
{"from" => 5, "to" => 7},
|
33
52
|
{"from" => 6, "to" => 7},
|
34
|
-
{"from" => 6, "to" =>
|
35
|
-
{"from" =>
|
36
|
-
|
53
|
+
{"from" => 6, "to" => 8},
|
54
|
+
{"from" => 7, "to" => 8},
|
55
|
+
{"from" => 9, "to" => 10},
|
56
|
+
{"from" => 9, "to" => 11},
|
57
|
+
{"from" => 10, "to" => 11},
|
58
|
+
{"from" => 10, "to" => 12},
|
59
|
+
{"from" => 11, "to" => 12},
|
60
|
+
{"from" => 13, "to" => 14},
|
61
|
+
{"from" => 13, "to" => 15},
|
62
|
+
{"from" => 14, "to" => 15},
|
63
|
+
{"from" => 14, "to" => 16},
|
64
|
+
{"from" => 15, "to" => 16},
|
65
|
+
{"from" => 4, "to" => 19},
|
66
|
+
{"from" => 4, "to" => 23},
|
67
|
+
{"from" => 8, "to" => 20},
|
68
|
+
{"from" => 8, "to" => 23},
|
69
|
+
{"from" => 12, "to" => 19},
|
70
|
+
{"from" => 12, "to" => 24},
|
71
|
+
{"from" => 16, "to" => 24},
|
72
|
+
{"from" => 16, "to" => 20},
|
73
|
+
{"from" => 17, "to" => 19},
|
74
|
+
{"from" => 18, "to" => 20},
|
75
|
+
{"from" => 21, "to" => 23},
|
76
|
+
{"from" => 22, "to" => 24},
|
77
|
+
{"from" => 3, "to" => 17},
|
78
|
+
{"from" => 10, "to" => 17},
|
79
|
+
{"from" => 7, "to" => 18},
|
80
|
+
{"from" => 15, "to" => 18},
|
81
|
+
{"from" => 6, "to" => 21},
|
82
|
+
{"from" => 2, "to" => 21},
|
83
|
+
{"from" => 11, "to" => 22},
|
84
|
+
{"from" => 14, "to" => 22}
|
85
|
+
],
|
86
|
+
"setup" => {
|
87
|
+
"2" => {
|
88
|
+
"0" => [{"node" => 1,"number_of_soldiers" => 5}],
|
89
|
+
"1" => [{"node" => 13,"number_of_soldiers" => 5}]
|
90
|
+
},
|
91
|
+
"4" => {
|
92
|
+
"0" => [{"node" => 1,"number_of_soldiers" => 5}],
|
93
|
+
"1" => [{"node" => 5, "number_of_soldiers" => 5}],
|
94
|
+
"2" => [{"node" => 9, "number_of_soldiers" => 5}],
|
95
|
+
"3" => [{"node" => 13, "number_of_soldiers" => 5}]
|
96
|
+
}
|
97
|
+
}
|
37
98
|
}
|
38
99
|
|
39
100
|
GAME_INFO = {
|
@@ -46,16 +107,6 @@ module Berlin
|
|
46
107
|
"player_id" => nil
|
47
108
|
}
|
48
109
|
|
49
|
-
GAME_STATE = [
|
50
|
-
{"node_id" => 1, "player_id" => nil, "number_of_soldiers" => 0},
|
51
|
-
{"node_id" => 2, "player_id" => nil, "number_of_soldiers" => 0},
|
52
|
-
{"node_id" => 3, "player_id" => nil, "number_of_soldiers" => 0},
|
53
|
-
{"node_id" => 4, "player_id" => nil, "number_of_soldiers" => 0},
|
54
|
-
{"node_id" => 5, "player_id" => nil, "number_of_soldiers" => 0},
|
55
|
-
{"node_id" => 6, "player_id" => nil, "number_of_soldiers" => 0},
|
56
|
-
{"node_id" => 7, "player_id" => nil, "number_of_soldiers" => 0},
|
57
|
-
{"node_id" => 8, "player_id" => nil, "number_of_soldiers" => 0}
|
58
|
-
]
|
59
110
|
|
60
111
|
Move = Struct.new(:player_id, :from, :to, :number_of_soldiers)
|
61
112
|
|
@@ -106,23 +157,18 @@ module Berlin
|
|
106
157
|
|
107
158
|
class Display
|
108
159
|
|
109
|
-
attr_accessor *(1..8).map{ |n| "n#{n}"}
|
110
|
-
|
111
160
|
COLORS = [:red, :green, :yellow, :blue]
|
112
161
|
|
113
|
-
|
114
|
-
|
115
|
-
def initialize(state)
|
116
|
-
js = state.as_json
|
117
|
-
@player_ids = js.map{ |n| n['player_id'] }.uniq.compact.sort
|
162
|
+
Position = Struct.new(:x, :y)
|
118
163
|
|
119
|
-
|
120
|
-
|
121
|
-
|
164
|
+
def initialize(map_definition, state)
|
165
|
+
@map_definition = map_definition
|
166
|
+
@state = state.state
|
167
|
+
@player_ids = @state.map{ |id, n| n['player_id'] }.uniq.compact.sort
|
122
168
|
|
123
|
-
|
124
|
-
|
125
|
-
|
169
|
+
@height, @width = TermInfo.screen_size
|
170
|
+
@height -= @player_ids.length + 1
|
171
|
+
@map = 1.upto(@height).map { [" "] * @width }
|
126
172
|
end
|
127
173
|
|
128
174
|
def color(player_id)
|
@@ -130,34 +176,90 @@ module Berlin
|
|
130
176
|
end
|
131
177
|
|
132
178
|
def as_display
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
/ \\ / \\ / \\
|
137
|
-
| #{n1.id} |---------| #{n2.id} |---------| #{n3.id} |
|
138
|
-
| #{n1.ns} | | #{n2.ns} | | #{n3.ns} |
|
139
|
-
\\____/ \\____/ \\____/
|
140
|
-
| \\ |
|
141
|
-
| \\ |
|
142
|
-
_+__ \\ _+__
|
143
|
-
/ \\ \\ / \\
|
144
|
-
| #{n4.id} |-----\\ \\------| #{n5.id} |
|
145
|
-
| #{n4.ns} | \\ | #{n5.ns} |
|
146
|
-
\\____/ \\ \\____/
|
147
|
-
| \\ |
|
148
|
-
| \\ |
|
149
|
-
_+__ \\___ _+__
|
150
|
-
/ \\ / \\ / \\
|
151
|
-
| #{n6.id} |---------| #{n7.id} |---------| #{n8.id} |
|
152
|
-
| #{n6.ns} | | #{n7.ns} | | #{n8.ns} |
|
153
|
-
\\____/ \\____/ \\____/
|
154
|
-
MAP
|
155
|
-
|
179
|
+
paths_as_display
|
180
|
+
nodes_as_display
|
181
|
+
map = @map.map(&:join).join("\n")
|
156
182
|
[map, *@player_ids.map{ |id| id.to_s.foreground(color(id)) }].join("\n")
|
157
183
|
end
|
184
|
+
|
185
|
+
def paths_as_display
|
186
|
+
@map_definition['paths'].each do |path|
|
187
|
+
from_node = @map_definition['nodes'][path['from']-1]
|
188
|
+
to_node = @map_definition['nodes'][path['to']-1]
|
189
|
+
|
190
|
+
from = node_position(from_node)
|
191
|
+
to = node_position(to_node)
|
192
|
+
|
193
|
+
draw_line(from, to)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def draw_line(from, to)
|
198
|
+
xs = range(from[0], to[0])
|
199
|
+
ys = range(from[1], to[1])
|
200
|
+
|
201
|
+
length = [xs.length, ys.length].max
|
202
|
+
|
203
|
+
(0...length).each do |n|
|
204
|
+
x = xs[(n.to_f/length * xs.length).floor]
|
205
|
+
y = ys[(n.to_f/length * ys.length).floor]
|
206
|
+
|
207
|
+
replace(x, y, PATH)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def range(from, to)
|
212
|
+
from > to ? (to..from).to_a.reverse : (from..to).to_a
|
213
|
+
end
|
214
|
+
|
215
|
+
def node_position(node)
|
216
|
+
x = (node['x'] / 100.0 * @width).to_i
|
217
|
+
y = (node['y'] / 100.0 * @height).to_i
|
218
|
+
[x, y]
|
219
|
+
end
|
220
|
+
|
221
|
+
def nodes_as_display
|
222
|
+
# ID###
|
223
|
+
# # 12#
|
224
|
+
# V###S
|
225
|
+
@map_definition['nodes'].each do |node|
|
226
|
+
node_state = @state[node['id']]
|
227
|
+
|
228
|
+
x, y = node_position(node)
|
229
|
+
|
230
|
+
player_color = color(node_state.player_id)
|
231
|
+
|
232
|
+
meta = @map_definition['types'].detect{|n| n['name'] == node['type']}
|
233
|
+
value = meta['soldiers_per_turn'] + meta['points']
|
234
|
+
|
235
|
+
wall = value > 0 ? CITY_WALL : NODE_WALL
|
236
|
+
(-1..1).each do |n|
|
237
|
+
replace(x-2, y+n, wall*5, player_color)
|
238
|
+
end
|
239
|
+
|
240
|
+
replace(x-2, y-1, node['id'])
|
241
|
+
number_of_soldiers = node_state.number_of_soldiers.to_s.center(3)
|
242
|
+
replace(x-1, y, number_of_soldiers, player_color)
|
243
|
+
|
244
|
+
if value > 0
|
245
|
+
soldiers_per_turn = meta['soldiers_per_turn'].to_s
|
246
|
+
replace(x-2, y+1, meta['points'])
|
247
|
+
replace(x+2, y+2 - soldiers_per_turn.length, soldiers_per_turn)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def replace(x, y, str, foreground = nil)
|
253
|
+
length = str.to_s.size
|
254
|
+
(0...length).each do |n|
|
255
|
+
char = str.to_s[n]
|
256
|
+
@map[y][x+n] = foreground ? char.foreground(foreground) : char
|
257
|
+
end
|
258
|
+
end
|
158
259
|
end
|
159
260
|
|
160
261
|
class State
|
262
|
+
attr_accessor :state
|
161
263
|
def initialize(from_json)
|
162
264
|
@state = from_json.inject({}) do |h, node|
|
163
265
|
h[node['node_id']] = NodeState.new(node['node_id'], node['player_id'], node['number_of_soldiers'])
|
@@ -181,9 +283,9 @@ module Berlin
|
|
181
283
|
def remove_soldiers(move)
|
182
284
|
origin = @state[move.from]
|
183
285
|
if origin.player_id != move.player_id
|
184
|
-
|
286
|
+
puts "Trying to move #{move.number_of_soldiers} soldiers from ##{move.from}. Node ##{move.from} belongs to #{origin.player_id}"
|
185
287
|
elsif origin.number_of_soldiers < move.number_of_soldiers
|
186
|
-
|
288
|
+
puts "Trying to move #{move.number_of_soldiers} soldiers from ##{move.from}. Only #{origin.number_of_soldiers} soldiers available"
|
187
289
|
else
|
188
290
|
origin.number_of_soldiers -= move.number_of_soldiers
|
189
291
|
puts "\t[#{move.player_id}] Moves #{move.number_of_soldiers} soldiers from ##{move.from} to ##{move.to}"
|
@@ -217,55 +319,81 @@ end
|
|
217
319
|
|
218
320
|
class Berlin::Fake::Game
|
219
321
|
|
220
|
-
def initialize(
|
221
|
-
@
|
222
|
-
|
223
|
-
@
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
node['
|
229
|
-
ai_info = Berlin::Fake::GAME_INFO.dup
|
230
|
-
ai_info['player_id'] = ai_name
|
231
|
-
ai_info['game_id'] = n
|
232
|
-
|
233
|
-
ai_game = Berlin::AI::Game.new
|
234
|
-
ai_game.id = ai_info['game_id']
|
235
|
-
ai_game.map = Berlin::AI::Map.parse(Berlin::Fake::MAP_DEFINITION.merge('player_id' => ai_info['player_id']))
|
236
|
-
ai_game.player_id = ai_info['player_id']
|
237
|
-
ai_game.time_limit_per_turn = ai_info['time_limit_per_turn']
|
238
|
-
ai_game.maximum_number_of_turns = ai_info['maximum_number_of_turns']
|
239
|
-
ai_game.number_of_players = ai_info['number_of_players']
|
240
|
-
ai_game
|
322
|
+
def initialize(options)
|
323
|
+
@options = options
|
324
|
+
number_of_ai = options[:test_ais]
|
325
|
+
@turn = 0
|
326
|
+
map_definition
|
327
|
+
@game_info = Berlin::Fake::GAME_INFO
|
328
|
+
|
329
|
+
@game_state = @map_definition['nodes'].map do |node|
|
330
|
+
{"node_id" => node['id'], "player_id" => nil, "number_of_soldiers" => 0}
|
241
331
|
end
|
242
332
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
@
|
257
|
-
|
258
|
-
|
259
|
-
|
333
|
+
@state = Berlin::Fake::State.new(@game_state.dup)
|
334
|
+
|
335
|
+
@city_nodes = @map_definition['nodes'].select{ |node| node['type'] == 'city' }.map{ |node| node['id'] }
|
336
|
+
|
337
|
+
start_points = @map_definition['setup'][(number_of_ai + 1).to_s]
|
338
|
+
|
339
|
+
unless start_points
|
340
|
+
puts("This map cannot be played with #{number_of_ai+1} players. #{@map_definition['setup'].keys.join(', ')} are possible only")
|
341
|
+
exit
|
342
|
+
end
|
343
|
+
|
344
|
+
players = 1.upto(number_of_ai).map{ |n| "AI ##{n}" } << "Player"
|
345
|
+
|
346
|
+
@ai_games = players.each.with_index.map do |name, index|
|
347
|
+
start_points[index.to_s].each do |point|
|
348
|
+
node = @state.state[point['node']]
|
349
|
+
|
350
|
+
node['player_id'] = name
|
351
|
+
node['number_of_soldiers'] = point['number_of_soldiers']
|
352
|
+
end
|
353
|
+
ai_info = @game_info.dup
|
354
|
+
ai_info['player_id'] = name
|
355
|
+
ai_info['game_id'] = index
|
356
|
+
|
357
|
+
map = Berlin::AI::Map.parse(@map_definition.dup.merge('player_id' => ai_info['player_id']))
|
358
|
+
game = Berlin::AI::Game.new
|
359
|
+
game.map = map
|
360
|
+
game.id = ai_info['game_id']
|
361
|
+
game.player_id = ai_info['player_id']
|
362
|
+
game.time_limit_per_turn = ai_info['time_limit_per_turn']
|
363
|
+
game.maximum_number_of_turns = ai_info['maximum_number_of_turns']
|
364
|
+
game.number_of_players = ai_info['number_of_players']
|
365
|
+
game.reset!
|
366
|
+
|
367
|
+
game
|
368
|
+
end
|
369
|
+
|
370
|
+
@player_game = @ai_games.pop
|
371
|
+
end
|
372
|
+
|
373
|
+
def map_definition
|
374
|
+
return @map_definition if @map_definition
|
375
|
+
if @options[:map_id]
|
376
|
+
uri = URI.parse("http://berlin-ai.com/maps/#{@options[:map_id]}.json")
|
377
|
+
response = Net::HTTP.get_response(uri)
|
378
|
+
begin
|
379
|
+
@map_definition = JSON(response.body).fetch('map').fetch('representation')
|
380
|
+
rescue => e
|
381
|
+
puts "There was a problem downloading the map #{@options[:map_id]}"
|
382
|
+
puts e.message
|
383
|
+
exit
|
384
|
+
end
|
385
|
+
else
|
386
|
+
@map_definition = Berlin::Fake::MAP_DEFINITION
|
387
|
+
end
|
260
388
|
end
|
261
389
|
|
262
390
|
def run
|
263
|
-
puts Berlin::Fake::Display.new(@state).as_display
|
391
|
+
puts Berlin::Fake::Display.new(@map_definition, @state).as_display
|
264
392
|
pause
|
265
393
|
while !@state.winner? && @turn < Berlin::Fake::GAME_INFO['maximum_number_of_turns']
|
266
394
|
turn
|
267
395
|
pause
|
268
|
-
puts Berlin::Fake::Display.new(@state).as_display
|
396
|
+
puts Berlin::Fake::Display.new(@map_definition, @state).as_display
|
269
397
|
pause
|
270
398
|
end
|
271
399
|
end
|
data/lib/berlin-ai.rb
CHANGED
@@ -17,7 +17,7 @@ set :verbose, true
|
|
17
17
|
set :logger, Logger.new(STDOUT)
|
18
18
|
|
19
19
|
# set tests to false
|
20
|
-
|
20
|
+
options = {}
|
21
21
|
|
22
22
|
# Parse options
|
23
23
|
OptionParser.new do |opts|
|
@@ -42,12 +42,16 @@ OptionParser.new do |opts|
|
|
42
42
|
set :logger, Logger.new(l || 'berlin.log')
|
43
43
|
end
|
44
44
|
|
45
|
+
opts.on("-m MAP_ID", "--map MAP_ID", "Which map to use from Berlin. Use in conjunction with TEST") do |m|
|
46
|
+
options[:map_id] = m
|
47
|
+
end
|
48
|
+
|
45
49
|
opts.on("-t N", "--test N", Integer, "Test against N random AI") do |t|
|
46
50
|
if t < 0 || t > 3
|
47
51
|
puts "This map supports a maximum of 3 AI"
|
48
52
|
exit 1
|
49
53
|
end
|
50
|
-
|
54
|
+
options[:test_ais] = t
|
51
55
|
end
|
52
56
|
|
53
57
|
opts.on("-v", "--verbose", "Print information to STDOUT") do
|
@@ -101,8 +105,8 @@ def log level, message
|
|
101
105
|
settings.logger.send(level, message) if settings.logger
|
102
106
|
end
|
103
107
|
|
104
|
-
if
|
105
|
-
at_exit { Berlin::Fake::Game.new(
|
108
|
+
if options[:test_ais]
|
109
|
+
at_exit { Berlin::Fake::Game.new(options).run }
|
106
110
|
else
|
107
111
|
set :app_file, $0
|
108
112
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: berlin-ai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Blais
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sinatra
|
@@ -68,6 +68,20 @@ dependencies:
|
|
68
68
|
- - ~>
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: 1.1.4
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: ruby-terminfo
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
71
85
|
- !ruby/object:Gem::Dependency
|
72
86
|
name: thin
|
73
87
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,28 +100,28 @@ dependencies:
|
|
86
100
|
name: minitest
|
87
101
|
requirement: !ruby/object:Gem::Requirement
|
88
102
|
requirements:
|
89
|
-
- -
|
103
|
+
- - '>='
|
90
104
|
- !ruby/object:Gem::Version
|
91
105
|
version: '0'
|
92
106
|
type: :development
|
93
107
|
prerelease: false
|
94
108
|
version_requirements: !ruby/object:Gem::Requirement
|
95
109
|
requirements:
|
96
|
-
- -
|
110
|
+
- - '>='
|
97
111
|
- !ruby/object:Gem::Version
|
98
112
|
version: '0'
|
99
113
|
- !ruby/object:Gem::Dependency
|
100
114
|
name: pry
|
101
115
|
requirement: !ruby/object:Gem::Requirement
|
102
116
|
requirements:
|
103
|
-
- -
|
117
|
+
- - '>='
|
104
118
|
- !ruby/object:Gem::Version
|
105
119
|
version: '0'
|
106
120
|
type: :development
|
107
121
|
prerelease: false
|
108
122
|
version_requirements: !ruby/object:Gem::Requirement
|
109
123
|
requirements:
|
110
|
-
- -
|
124
|
+
- - '>='
|
111
125
|
- !ruby/object:Gem::Version
|
112
126
|
version: '0'
|
113
127
|
description: Berlin Artificial Intelligence
|
@@ -120,7 +134,7 @@ executables:
|
|
120
134
|
extensions: []
|
121
135
|
extra_rdoc_files: []
|
122
136
|
files:
|
123
|
-
- CHANGELOG
|
137
|
+
- CHANGELOG.md
|
124
138
|
- Gemfile
|
125
139
|
- Gemfile.lock
|
126
140
|
- LICENSE
|
@@ -144,7 +158,8 @@ files:
|
|
144
158
|
- test/node_test.rb
|
145
159
|
- test/test_ai.rb
|
146
160
|
homepage: http://github.com/thirdside/berlin-ai
|
147
|
-
licenses:
|
161
|
+
licenses:
|
162
|
+
- copyleft
|
148
163
|
metadata: {}
|
149
164
|
post_install_message:
|
150
165
|
rdoc_options: []
|
@@ -153,17 +168,17 @@ require_paths:
|
|
153
168
|
- test
|
154
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
155
170
|
requirements:
|
156
|
-
- -
|
171
|
+
- - '>='
|
157
172
|
- !ruby/object:Gem::Version
|
158
173
|
version: '0'
|
159
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
175
|
requirements:
|
161
|
-
- -
|
176
|
+
- - '>='
|
162
177
|
- !ruby/object:Gem::Version
|
163
178
|
version: '0'
|
164
179
|
requirements: []
|
165
180
|
rubyforge_project:
|
166
|
-
rubygems_version: 2.
|
181
|
+
rubygems_version: 2.0.14
|
167
182
|
signing_key:
|
168
183
|
specification_version: 4
|
169
184
|
summary: Berlin Artificial Intelligence
|