berlin-ai 0.0.38 → 0.0.39
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 +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
|