berlin-ai 0.0.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.
- data/LICENSE +6 -0
- data/README +0 -0
- data/berlin-ai.gemspec +29 -0
- data/lib/ai/game.rb +51 -0
- data/lib/ai/map.rb +66 -0
- data/lib/ai/node.rb +37 -0
- data/lib/berlin-ai.rb +23 -0
- data/lib/version.rb +9 -0
- data/test/test_ai.rb +17 -0
- metadata +81 -0
data/LICENSE
ADDED
data/README
ADDED
File without changes
|
data/berlin-ai.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'lib/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "berlin-ai"
|
9
|
+
s.version = Berlin::AI::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Christian Blais", "Guillaume Malette", "Jodi Giordano"]
|
12
|
+
s.email = ["christ.blais@gmail.com", "gmalette@gmail.com", "giordano.jodi@gmail.com"]
|
13
|
+
s.homepage = "http://github.com/christianblais/berlin-ai"
|
14
|
+
s.summary = "Berlin Artificial Intelligence"
|
15
|
+
s.description = "Berlin Artificial Intelligence"
|
16
|
+
|
17
|
+
s.files = [
|
18
|
+
'LICENSE',
|
19
|
+
'README',
|
20
|
+
'berlin-ai.gemspec',
|
21
|
+
'lib/berlin-ai.rb',
|
22
|
+
'lib/version.rb',
|
23
|
+
'lib/ai/game.rb',
|
24
|
+
'lib/ai/map.rb',
|
25
|
+
'lib/ai/node.rb',
|
26
|
+
'test/test_ai.rb']
|
27
|
+
|
28
|
+
s.require_paths = ['lib', 'test']
|
29
|
+
end
|
data/lib/ai/game.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Berlin
|
2
|
+
module AI
|
3
|
+
class Game
|
4
|
+
attr_reader :id
|
5
|
+
|
6
|
+
@@games = {}
|
7
|
+
|
8
|
+
def self.create_or_update action, infos, map, state
|
9
|
+
# Check for params and quit on errors
|
10
|
+
return nil if action.nil? || infos.nil? || map.nil? || state.nil?
|
11
|
+
|
12
|
+
# First, we parse the received request
|
13
|
+
infos = JSON.parse( infos )
|
14
|
+
map = JSON.parse( map )
|
15
|
+
state = JSON.parse( state )
|
16
|
+
|
17
|
+
# Then, let's see if we can find that game. If not, register it.
|
18
|
+
game_id = infos['game_id']
|
19
|
+
@@games[game_id] ||= Berlin::AI::Game.new game_id, map, infos
|
20
|
+
game = @@games[game_id]
|
21
|
+
|
22
|
+
if action == "game_over"
|
23
|
+
# Release the game to avoid memory leaks
|
24
|
+
@@games[game_id] = nil
|
25
|
+
elsif state
|
26
|
+
# Now, we want to update the current state of the game with the new content
|
27
|
+
game.update state
|
28
|
+
end
|
29
|
+
|
30
|
+
game
|
31
|
+
end
|
32
|
+
|
33
|
+
# @id = Uniq game ID (params[:game])
|
34
|
+
# @map = Current state of the game (params[:json])
|
35
|
+
def initialize id, map, infos
|
36
|
+
@id = id
|
37
|
+
@map = Berlin::AI::Map.new map, infos
|
38
|
+
end
|
39
|
+
|
40
|
+
# Let's update the map with the latest state
|
41
|
+
def update state
|
42
|
+
@map.update state
|
43
|
+
end
|
44
|
+
|
45
|
+
# Must be overwritten
|
46
|
+
def turn_moves
|
47
|
+
raise "Please... overwrite me!"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/ai/map.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Berlin
|
2
|
+
module AI
|
3
|
+
# Map will keep track of all the useful information needed to play, such as
|
4
|
+
# nodes, points, soldiers, etc. Game will then be able to pick any information
|
5
|
+
# it wants from map to decide what are the best moves to do.
|
6
|
+
class Map
|
7
|
+
attr_accessor :nodes
|
8
|
+
attr_reader :player_id
|
9
|
+
|
10
|
+
def initialize map, infos
|
11
|
+
@player_id = infos['player_id']
|
12
|
+
@nodes = {}
|
13
|
+
@directed = infos['directed'] || false
|
14
|
+
|
15
|
+
# Let's parse json['nodes'] and register all nodes we can find.
|
16
|
+
# We'll keep track of them in @nodes so we can find them later.
|
17
|
+
# At this step (Map creation...), we still don't know who possess
|
18
|
+
# the node and how many soldiers there is. We'll get back to that later.
|
19
|
+
# json['nodes'] => [{:id => STRING}, ...]
|
20
|
+
map['nodes'].each do |node|
|
21
|
+
@nodes[node['id']] = Berlin::AI::Node.new node['id']
|
22
|
+
end
|
23
|
+
|
24
|
+
# Same thing here, with paths.
|
25
|
+
# json['paths'] => [{:from => INTEGER, :to => INTEGER}, ...]
|
26
|
+
map['paths'].each do |path|
|
27
|
+
@nodes[path['from']].link_to @nodes[path['to']]
|
28
|
+
|
29
|
+
# Don't forget! If the map is not directed, we must create the reverse link!
|
30
|
+
@nodes[path['to']].link_to @nodes[path['from']] unless directed?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# By checking node.player_id, we are able to know if we own the node or not.
|
35
|
+
def owned_nodes
|
36
|
+
@nodes.select do |id, node|
|
37
|
+
node.player_id == player_id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# We can now loop on our owned nodes in order to find our controlled nodes.
|
42
|
+
def controlled_nodes
|
43
|
+
owned_nodes.select do |id, node|
|
44
|
+
node.occupied?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Is the map directed?
|
49
|
+
def directed?
|
50
|
+
@directed
|
51
|
+
end
|
52
|
+
|
53
|
+
# Let's update the current state with the latest provided info! With this step,
|
54
|
+
# we'll now know who possess the node and how many soldiers there is.
|
55
|
+
# state contains an array of nodes, so we just have to loop on it.
|
56
|
+
# state => [{:node_id => STRING, :number_of_soldiers => INTEGER, :player_id => INTEGER}, ...]
|
57
|
+
def update state
|
58
|
+
state.each do |n|
|
59
|
+
node = @nodes[n['node_id']]
|
60
|
+
node.number_of_soldiers = n['number_of_soldiers']
|
61
|
+
node.player_id = n['player_id']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/ai/node.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Berlin
|
2
|
+
module AI
|
3
|
+
# Node will help us to keep track of possible moves.
|
4
|
+
# We'll be able to use it in order to know if two
|
5
|
+
# nodes are adjacent, how much points worth a node, etc.
|
6
|
+
class Node
|
7
|
+
attr_accessor :id, :player_id, :number_of_soldiers
|
8
|
+
|
9
|
+
def initialize id
|
10
|
+
@id = id
|
11
|
+
@number_of_soldiers = 0
|
12
|
+
@player_id = 0
|
13
|
+
@links = []
|
14
|
+
end
|
15
|
+
|
16
|
+
# Register a given node as an adjacent one.
|
17
|
+
def link_to other_node
|
18
|
+
@links << other_node
|
19
|
+
end
|
20
|
+
|
21
|
+
# Is other_node adjacents to current node?
|
22
|
+
def adjacent? other_node
|
23
|
+
@links.include? other_node
|
24
|
+
end
|
25
|
+
|
26
|
+
# Is there anybody out there?
|
27
|
+
def occupied?
|
28
|
+
@number_of_soldiers > 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# What are current node's neighbors?
|
32
|
+
def adjacent_nodes
|
33
|
+
@links.dup
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/berlin-ai.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
%w(game map node).each do |file|
|
2
|
+
require File.expand_path( File.dirname( __FILE__ ) ) + "/ai/#{file}"
|
3
|
+
end
|
4
|
+
|
5
|
+
post '/' do
|
6
|
+
begin
|
7
|
+
if ['turn', 'game_start', 'game_over'].include? params[:action]
|
8
|
+
game = Berlin::AI::Game.create_or_update params[:action], params[:infos], params[:map], params[:state]
|
9
|
+
|
10
|
+
if params[:action] == 'turn'
|
11
|
+
# Respond with a json of our moves
|
12
|
+
return game.turn_moves.to_json
|
13
|
+
end
|
14
|
+
else
|
15
|
+
p params.inspect
|
16
|
+
end
|
17
|
+
|
18
|
+
# For every other type of request, respond with 200 OK
|
19
|
+
200
|
20
|
+
rescue Exception => e
|
21
|
+
500
|
22
|
+
end
|
23
|
+
end
|
data/lib/version.rb
ADDED
data/test/test_ai.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'yajl/json_gem'
|
4
|
+
|
5
|
+
%w(berlin-ai).each do |file|
|
6
|
+
require File.expand_path( File.dirname( __FILE__ ) ) + "/../lib/#{file}"
|
7
|
+
end
|
8
|
+
|
9
|
+
module Berlin
|
10
|
+
module AI
|
11
|
+
class Game
|
12
|
+
def turn_moves
|
13
|
+
p "salut"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: berlin-ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Christian Blais
|
14
|
+
- Guillaume Malette
|
15
|
+
- Jodi Giordano
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2011-05-19 00:00:00 -04:00
|
21
|
+
default_executable:
|
22
|
+
dependencies: []
|
23
|
+
|
24
|
+
description: Berlin Artificial Intelligence
|
25
|
+
email:
|
26
|
+
- christ.blais@gmail.com
|
27
|
+
- gmalette@gmail.com
|
28
|
+
- giordano.jodi@gmail.com
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- LICENSE
|
37
|
+
- README
|
38
|
+
- berlin-ai.gemspec
|
39
|
+
- lib/berlin-ai.rb
|
40
|
+
- lib/version.rb
|
41
|
+
- lib/ai/game.rb
|
42
|
+
- lib/ai/map.rb
|
43
|
+
- lib/ai/node.rb
|
44
|
+
- test/test_ai.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/christianblais/berlin-ai
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
- test
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Berlin Artificial Intelligence
|
80
|
+
test_files: []
|
81
|
+
|