swint 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +23 -0
- data/LICENSE +20 -0
- data/README +80 -0
- data/Rakefile +59 -0
- data/bin/swint +75 -0
- data/lib/swint/_constants.rb +30 -0
- data/lib/swint/abstract_robot.rb +125 -0
- data/lib/swint/class_robot.rb +48 -0
- data/lib/swint/field.rb +27 -0
- data/lib/swint/game.rb +129 -0
- data/lib/swint/map.rb +65 -0
- data/lib/swint/result.rb +33 -0
- data/lib/swint/robot.rb +125 -0
- data/lib/swint/xmlrpc_robot.rb +47 -0
- data/lib/swint_basics/array.rb +18 -0
- data/lib/swint_basics/hash.rb +11 -0
- metadata +70 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
2008-01-17 v0.5 features
|
2
|
+
|
3
|
+
* -e und -c to require and use a ruby robot class
|
4
|
+
for debugging and profiling purposes
|
5
|
+
|
6
|
+
2008-01-14 v0.4 features
|
7
|
+
|
8
|
+
* use -n <n> for more than one game
|
9
|
+
* use -i for timing statistics
|
10
|
+
|
11
|
+
2008-01-07 v0.3 bug fixes
|
12
|
+
|
13
|
+
* map is rotated, turn this behavior off with option -t
|
14
|
+
* code now splited in several files
|
15
|
+
* walking on start is now possible
|
16
|
+
|
17
|
+
2008-01-06 v0.2 lots of minor improvements
|
18
|
+
|
19
|
+
* less flickering
|
20
|
+
* use -s to see every step
|
21
|
+
* use -w to wait for input each step
|
22
|
+
|
23
|
+
2008-01-02 v0.1 initial release
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Philipp Hofmann <phil@s126.de>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
================================================================================
|
3
|
+
__ __ __
|
4
|
+
.-----.--.--.--.|__|.-----.| |_ .----.| |--.
|
5
|
+
|__ --| | | || || || _|__| _|| _ |
|
6
|
+
|_____|________||__||__|__||____|__|__| |_____|
|
7
|
+
|
8
|
+
(c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
9
|
+
================================================================================
|
10
|
+
|
11
|
+
swint.rb is an entirely in Ruby written client for the SwarmIntelligence
|
12
|
+
programming game originally created by Stefan Schwarzburg-Benz.
|
13
|
+
|
14
|
+
Usage:
|
15
|
+
|
16
|
+
./swint.rb [options]
|
17
|
+
|
18
|
+
|
19
|
+
Options:
|
20
|
+
|
21
|
+
-r|--robot <uri>
|
22
|
+
|
23
|
+
supply a URL to your robot's XMLRPC interface here, may be used repeatedly
|
24
|
+
|
25
|
+
|
26
|
+
-m|--map <filename>
|
27
|
+
|
28
|
+
supply a filename to the XML map of the game
|
29
|
+
|
30
|
+
|
31
|
+
-s|--step
|
32
|
+
|
33
|
+
visualize each step, not only each turn
|
34
|
+
|
35
|
+
|
36
|
+
-w|--wait
|
37
|
+
|
38
|
+
wait for input before each step
|
39
|
+
|
40
|
+
|
41
|
+
-v|--no-visual
|
42
|
+
|
43
|
+
turn off visuals
|
44
|
+
|
45
|
+
|
46
|
+
-t|--test
|
47
|
+
|
48
|
+
turn off the initial rotation of map (better for testing)
|
49
|
+
|
50
|
+
|
51
|
+
-n|--n-times <times>
|
52
|
+
|
53
|
+
play more than one game
|
54
|
+
|
55
|
+
|
56
|
+
-i|--statistics
|
57
|
+
|
58
|
+
display statistics
|
59
|
+
|
60
|
+
|
61
|
+
-e|--require <file>
|
62
|
+
|
63
|
+
require a ruby file
|
64
|
+
|
65
|
+
|
66
|
+
-c|--class
|
67
|
+
|
68
|
+
add a ruby robot class as player
|
69
|
+
|
70
|
+
|
71
|
+
Example:
|
72
|
+
|
73
|
+
For a quick match on example.map:
|
74
|
+
|
75
|
+
./swint.rb -r http://localhost:8000/ -r http://localhost:8001/
|
76
|
+
|
77
|
+
For testing your bot:
|
78
|
+
|
79
|
+
./swint.rb -r http://localhost:8000/ -s -t -w -m maps/example.map
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
Gem::manage_gems
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
# REQUIRED
|
8
|
+
|
9
|
+
s.name = "swint"
|
10
|
+
s.version = "0.5"
|
11
|
+
s.summary = "a console client for the swarm intelligence programming game"
|
12
|
+
|
13
|
+
# REQUIRED AND SET BY DEFAULT
|
14
|
+
|
15
|
+
# s.platform = Gem::Platform::RUBY
|
16
|
+
# s.date = Time.now
|
17
|
+
# s.require_paths = ['lib']
|
18
|
+
|
19
|
+
# OPTIONAL
|
20
|
+
|
21
|
+
s.description = s.summary
|
22
|
+
#s.files = Dir.glob("**/*").delete_if { |item| /(.svn|~$|Rakefile|pkg)/.match(item) }
|
23
|
+
s.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
|
24
|
+
#s.authors = ['Philipp Hofmann']
|
25
|
+
s.author = 'Philipp Hofmann'
|
26
|
+
s.email = "phil @nospam@ branch14.org"
|
27
|
+
s.homepage = "http://branch14.org/swint/"
|
28
|
+
s.rubyforge_project = s.name
|
29
|
+
s.extra_rdoc_files = ['README', 'LICENSE', 'CHANGELOG']
|
30
|
+
s.executables = [s.name]
|
31
|
+
# s.default_executable = s.name
|
32
|
+
|
33
|
+
# OPTIONAL AND SET BY DEFAULT
|
34
|
+
|
35
|
+
# s.autorequire = nil
|
36
|
+
# s.bindir = 'bin'
|
37
|
+
# s.has_rdoc = false
|
38
|
+
# s.rdoc_options = []
|
39
|
+
# s.required_ruby_version = '> 0.0.0'
|
40
|
+
# s.requirements = []
|
41
|
+
# s.test_files = []
|
42
|
+
# s.dependencies = []
|
43
|
+
# s.add_dependency('log4r', '>= 1.0.5')
|
44
|
+
# s.extensions = []
|
45
|
+
|
46
|
+
# SET AUTOMATICALLY
|
47
|
+
|
48
|
+
# rubygems_version, specification_version
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
53
|
+
pkg.need_tar = true
|
54
|
+
end
|
55
|
+
|
56
|
+
task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
|
57
|
+
puts "generated latest version"
|
58
|
+
end
|
59
|
+
|
data/bin/swint
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-17 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
##############################
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'ostruct'
|
10
|
+
require 'xmlrpc/client'
|
11
|
+
require 'rexml/document'
|
12
|
+
|
13
|
+
##############################
|
14
|
+
|
15
|
+
# $:.unshift(File.dirname(__FILE__))
|
16
|
+
|
17
|
+
require 'swint_basics/array'
|
18
|
+
require 'swint_basics/hash'
|
19
|
+
|
20
|
+
require 'swint/_constants'
|
21
|
+
require 'swint/game'
|
22
|
+
require 'swint/map'
|
23
|
+
require 'swint/field'
|
24
|
+
require 'swint/result'
|
25
|
+
require 'swint/abstract_robot'
|
26
|
+
require 'swint/xmlrpc_robot'
|
27
|
+
require 'swint/class_robot'
|
28
|
+
|
29
|
+
##############################
|
30
|
+
|
31
|
+
config = OpenStruct.new
|
32
|
+
config.step = false
|
33
|
+
config.wait = false
|
34
|
+
config.visual = true
|
35
|
+
config.map = 'example.map'
|
36
|
+
config.robots = []
|
37
|
+
config.ntimes = 1
|
38
|
+
config.statistics = false
|
39
|
+
|
40
|
+
opts = OptionParser.new do |o|
|
41
|
+
o.on('-r', '--robot URI', 'URI of robot') { |r| config.robots << r }
|
42
|
+
o.on('-m', '--map URI', 'URI of map') { |m| config.map = m }
|
43
|
+
o.on('-s', '--step', 'Show each step') { config.step = true }
|
44
|
+
o.on('-w', '--wait', 'Wait for return after visual') { config.wait = true }
|
45
|
+
o.on('-v', '--no-visual', 'No visual at all') { config.visual = false }
|
46
|
+
o.on('-t', '--test', 'Do not rotate map') { config.test = true }
|
47
|
+
o.on('-n', '--n-times TIMES', 'Run n games') { |n| config.ntimes = n.to_i }
|
48
|
+
o.on('-i', '--statistics', 'Display statistics') { config.statistics = true }
|
49
|
+
o.on('-e', '--require FILENAME', 'Provide a file to require') { |e| require(e) }
|
50
|
+
o.on('-c', '--class CLASS', 'Provide a Ruby Robot Class') { |c| config.robots << Kernel.const_get(c) }
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.parse!(ARGV)
|
54
|
+
|
55
|
+
Swint.rotate_map! unless config.test
|
56
|
+
|
57
|
+
unless File.exist?(config.map)
|
58
|
+
puts "mapfile #{config.map} not found"
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
|
62
|
+
config.ntimes.times do
|
63
|
+
game = Swint::Game.new(config)
|
64
|
+
result = game.run
|
65
|
+
puts "winner after % 3s rounds robot %s" % [result.rounds, result.winner]
|
66
|
+
if config.statistics
|
67
|
+
puts "\ntiming statistics\n-----------------"
|
68
|
+
puts "game took %5.2f seconds" % result.time
|
69
|
+
result.data.each do |r, d|
|
70
|
+
time = 0
|
71
|
+
d[:times].each { |t| time += t }
|
72
|
+
puts "% 5.2f seconds %s (%s)" % [time, d[:robot].name, d[:robot].owner]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
CHAR = {
|
9
|
+
:free => '_',
|
10
|
+
:object => 'o',
|
11
|
+
:start => 'S',
|
12
|
+
:goal => 'G',
|
13
|
+
:outside => '#',
|
14
|
+
:energy => '!'
|
15
|
+
}
|
16
|
+
|
17
|
+
DIRV = [
|
18
|
+
[-1, +1],
|
19
|
+
[-1, 0],
|
20
|
+
[ 0, -1],
|
21
|
+
[+1, -1],
|
22
|
+
[+1, 0],
|
23
|
+
[ 0, +1]
|
24
|
+
]
|
25
|
+
|
26
|
+
def Swint.rotate_map!
|
27
|
+
DIRV.push DIRV.shift, DIRV.shift, DIRV.shift
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class AbstractRobot
|
9
|
+
|
10
|
+
attr_accessor :pos
|
11
|
+
|
12
|
+
attr_reader :speed, :sight, :power, :energy, :weight, :energy_left, :uri, :name, :owner
|
13
|
+
|
14
|
+
# --------------------------------------------------------------------------------
|
15
|
+
# --- stub
|
16
|
+
|
17
|
+
def initialize(uri, pos)
|
18
|
+
@uri = uri
|
19
|
+
@pos = pos
|
20
|
+
restore
|
21
|
+
end
|
22
|
+
|
23
|
+
def next(map)
|
24
|
+
end
|
25
|
+
|
26
|
+
def move
|
27
|
+
# check_direction(...)
|
28
|
+
end
|
29
|
+
|
30
|
+
def push
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_game(msg)
|
34
|
+
end
|
35
|
+
|
36
|
+
# --------------------------------------------------------------------------------
|
37
|
+
|
38
|
+
def is_valid?
|
39
|
+
(@speed + @sight + @power + @energy + @weight) == 22
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_direction(d)
|
43
|
+
unless (0..5).include?(d)
|
44
|
+
puts "#{@name}, what is this? '#{d}' is not a drection."
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
d
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_action(a)
|
51
|
+
unless [:do_nothing, :move_to, :push_object, :shout].include?(a)
|
52
|
+
puts "#{@name}, what is this? '#{a}' is not an action."
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
a
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
a = ["#{@name} (#{@owner})", @speed, @sight, @power, @weight, @energy]
|
60
|
+
"%-30s [sp: % 2s, si: % 2s, po: % 2s, we: % 2s, en: % 2s]" % a
|
61
|
+
end
|
62
|
+
|
63
|
+
def use_energy?
|
64
|
+
return false unless has_energy?
|
65
|
+
@energy_left -= 1
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_energy?
|
70
|
+
@energy_left>0
|
71
|
+
end
|
72
|
+
|
73
|
+
def restore
|
74
|
+
@energy_left = @energy
|
75
|
+
end
|
76
|
+
|
77
|
+
def calculate_view(map)
|
78
|
+
|
79
|
+
# A centered hexagonal number, or hex number, is a centered figurate
|
80
|
+
# number that represents a hexagon with a dot in the center and all
|
81
|
+
# other dots surrounding the center dot in a hexagonal lattice.
|
82
|
+
# 1, 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397, 469, 547, 631, 721, 817, 919
|
83
|
+
|
84
|
+
# relative directions
|
85
|
+
reld = [2, 3, 4, 5, 0, 1]
|
86
|
+
|
87
|
+
data = []
|
88
|
+
cpos = pos.clone # that was tough!
|
89
|
+
|
90
|
+
### stef's version
|
91
|
+
|
92
|
+
sight.times do |depth|
|
93
|
+
cpos.add!(DIRV[0])
|
94
|
+
data << map.state_of_field(cpos)
|
95
|
+
5.times do |dir|
|
96
|
+
(depth+1).times do |i|
|
97
|
+
cpos.add!(DIRV[reld[dir]])
|
98
|
+
data << map.state_of_field(cpos)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
depth.times do |i|
|
102
|
+
cpos.add!(DIRV[reld[5]])
|
103
|
+
data << map.state_of_field(cpos)
|
104
|
+
end
|
105
|
+
cpos.add!(DIRV[1])
|
106
|
+
end
|
107
|
+
|
108
|
+
### sight.times do |depth|
|
109
|
+
### cpos.add!(DIRV[0])
|
110
|
+
### data << map.state_of_field(cpos)
|
111
|
+
### 6.times do |dir|
|
112
|
+
### (depth+1).times do |i|
|
113
|
+
### cpos.add!(DIRV[reld[dir]])
|
114
|
+
### data << map.state_of_field(cpos)
|
115
|
+
### end
|
116
|
+
### end
|
117
|
+
### end
|
118
|
+
|
119
|
+
data
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class ClassRobot < AbstractRobot
|
9
|
+
|
10
|
+
attr_accessor :pos
|
11
|
+
|
12
|
+
attr_reader :speed, :sight, :power, :energy, :weight, :energy_left, :uri, :name, :owner
|
13
|
+
|
14
|
+
def initialize(klass, pos)
|
15
|
+
@klass = klass
|
16
|
+
@instance = klass.new
|
17
|
+
# a = [:speed, :sight, :power, :energy, :weight, :name, :owner]
|
18
|
+
# a.each { |attr| send("self.#{attr}=", @instance.send(attr)) }
|
19
|
+
@speed = @instance.speed
|
20
|
+
@sight = @instance.sight
|
21
|
+
@power = @instance.power
|
22
|
+
@energy = @instance.energy
|
23
|
+
@weight = @instance.weight
|
24
|
+
@name = @instance.name
|
25
|
+
@owner = @instance.owner
|
26
|
+
@pos = pos
|
27
|
+
restore
|
28
|
+
end
|
29
|
+
|
30
|
+
def next(map)
|
31
|
+
check_action(@instance.next(calculate_view(map)).to_sym)
|
32
|
+
end
|
33
|
+
|
34
|
+
def move
|
35
|
+
check_direction(@instance.move)
|
36
|
+
end
|
37
|
+
|
38
|
+
def push
|
39
|
+
check_direction(@instance.push)
|
40
|
+
end
|
41
|
+
|
42
|
+
def end_game(msg)
|
43
|
+
@instance.end_game(msg)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/swint/field.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
# ------------------------------------------------------------
|
7
|
+
|
8
|
+
module Swint
|
9
|
+
|
10
|
+
class Field
|
11
|
+
|
12
|
+
attr_accessor :robot
|
13
|
+
attr_reader :pos
|
14
|
+
|
15
|
+
def initialize(s, pos)
|
16
|
+
@pos, @state = pos, s
|
17
|
+
@robot = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def state
|
21
|
+
@robot ? :robot : @state
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
data/lib/swint/game.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-14 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class Game
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@config = config
|
12
|
+
@robots = Hash.new
|
13
|
+
@map = Swint::Map.new.load_from_xml(File.new(config.map).read)
|
14
|
+
config.robots.each do |r|
|
15
|
+
puts "connecting to robot: #{r}" if config.visual
|
16
|
+
@robots[@robots.size+1] = Swint::XmlrpcRobot.new(r, @map.start) if r.is_a?(String)
|
17
|
+
@robots[@robots.size+1] = Swint::ClassRobot.new(r, @map.start) if r.is_a?(Class)
|
18
|
+
end
|
19
|
+
@result = Result.new(@robots)
|
20
|
+
@game_end = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
system "clear" if @config.visual
|
25
|
+
@robots.shuffle!
|
26
|
+
counter = 0
|
27
|
+
@result.start = Time.now
|
28
|
+
until @game_end
|
29
|
+
counter += 1
|
30
|
+
no_robot_left = true
|
31
|
+
@robots.each do |k, r|
|
32
|
+
r.speed.times do |step|
|
33
|
+
if !@game_end
|
34
|
+
answer = :do_nothing
|
35
|
+
dt = measure { answer = r.next(@map) } if r.has_energy?
|
36
|
+
case answer
|
37
|
+
|
38
|
+
when :move_to
|
39
|
+
no_robot_left = false
|
40
|
+
if r.use_energy?
|
41
|
+
dir = nil
|
42
|
+
dt += measure { dir = r.move }
|
43
|
+
npos = r.pos.add(DIRV[dir])
|
44
|
+
nstate = @map.state_of_field(npos)
|
45
|
+
if nstate==:goal
|
46
|
+
@robots.each { |key, b| b.end_game( (b==r) ? 'winner' : 'looser' ) }
|
47
|
+
@result.winner = k
|
48
|
+
@game_end = true
|
49
|
+
end
|
50
|
+
if [:free, :energy, :start].include?(nstate)
|
51
|
+
f, p = @map.fields[npos], @map.fields[r.pos]
|
52
|
+
r.restore if f.state==:energy
|
53
|
+
p.robot = false
|
54
|
+
f.robot = true
|
55
|
+
r.pos = npos
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
when :push_object
|
60
|
+
no_robot_left = false
|
61
|
+
if r.use_energy?
|
62
|
+
dir = nil
|
63
|
+
dt += measure { dir = r.push }
|
64
|
+
opos = r.pos.add(DIRV[dir])
|
65
|
+
ppos = opos.add(DIRV[dir])
|
66
|
+
ostate = @map.state_of_field(opos)
|
67
|
+
pstate = @map.state_of_field(ppos)
|
68
|
+
|
69
|
+
if pstate==:free
|
70
|
+
if ostate==:object
|
71
|
+
# ...
|
72
|
+
end
|
73
|
+
if ostate==:robot
|
74
|
+
# ...
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
@result.step(k, dt || 0)
|
83
|
+
# end of step
|
84
|
+
visualize(counter, step) if @config.visual && @config.step
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
# end of robot
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
# end of turn
|
95
|
+
visualize(counter) if @config.visual && !@config.step
|
96
|
+
|
97
|
+
if no_robot_left
|
98
|
+
@robots.each { |k, b| b.end_game('looser') }
|
99
|
+
@game_end = true
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
# end of game
|
105
|
+
@result.rounds = counter
|
106
|
+
@result.end = Time.now
|
107
|
+
@result
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
def visualize(round, step=nil)
|
112
|
+
system "tput cup 0 0"
|
113
|
+
print "ROUND: #{round}"
|
114
|
+
print " | STEP: #{step}" if step
|
115
|
+
puts
|
116
|
+
@robots.each { |k, r| puts "%s. [% 2s/% 2s] %s" % [k, r.energy_left, r.energy, r] }
|
117
|
+
@map.print_map(@robots)
|
118
|
+
gets if @config.wait
|
119
|
+
end
|
120
|
+
|
121
|
+
def measure
|
122
|
+
t = Time.now.to_f
|
123
|
+
yield
|
124
|
+
Time.now.to_f - t
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
data/lib/swint/map.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class Map
|
9
|
+
|
10
|
+
attr_reader :start, :fields
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@min, @max = [0, 0], [0, 0] # THIS IS AN ASUMPTION!
|
14
|
+
@fields = Hash.new(:outside)
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_from_xml(xml)
|
18
|
+
doc = REXML::Document.new(xml)
|
19
|
+
doc.elements.each('map/field') do |e|
|
20
|
+
v = e.attribute('v').value.to_i
|
21
|
+
u = e.attribute('u').value.to_i
|
22
|
+
s = e.attribute('state').value.to_sym
|
23
|
+
f = Swint::Field.new(s, [u, v])
|
24
|
+
@fields[f.pos] = f
|
25
|
+
@min[0] = u if u < @min[0]
|
26
|
+
@min[1] = v if v < @min[1]
|
27
|
+
@max[0] = u if u > @max[0]
|
28
|
+
@max[1] = v if v > @max[1]
|
29
|
+
if s==:start
|
30
|
+
@start = [u, v]
|
31
|
+
# f.robot = true # HACK!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def state_of_field(pos)
|
38
|
+
v = @fields[pos]
|
39
|
+
v.is_a?(Symbol) ? v : v.state
|
40
|
+
end
|
41
|
+
|
42
|
+
def print_map(robots)
|
43
|
+
w = ((@max[0]-@min[0])*2+(@max[1]-@min[1]))
|
44
|
+
border = '='*(w+6)
|
45
|
+
puts border
|
46
|
+
for y in @min[1]..@max[1]
|
47
|
+
line = ''
|
48
|
+
line += ' '*(y)
|
49
|
+
for x in @min[0]..@max[0]
|
50
|
+
s = state_of_field([x, y])
|
51
|
+
c = s!=:robot ? CHAR[state_of_field([x, y])] : robotkey_at(robots, [x, y]).to_s
|
52
|
+
line += c+' '
|
53
|
+
end
|
54
|
+
puts line
|
55
|
+
end
|
56
|
+
puts border
|
57
|
+
end
|
58
|
+
|
59
|
+
def robotkey_at(robots, pos)
|
60
|
+
robots.each { |k, r| return k if r.pos==pos }
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/lib/swint/result.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-14 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class Result
|
9
|
+
|
10
|
+
attr_accessor :winner, :rounds, :start, :end
|
11
|
+
attr_reader :data
|
12
|
+
|
13
|
+
def initialize(robots)
|
14
|
+
@data = Hash.new
|
15
|
+
@winner = '<no winner>'
|
16
|
+
robots.each do |k, r|
|
17
|
+
@data[k] = Hash.new
|
18
|
+
@data[k][:robot] = r
|
19
|
+
@data[k][:times] = []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def step(robot, time)
|
24
|
+
@data[robot][:times] << time
|
25
|
+
end
|
26
|
+
|
27
|
+
def time
|
28
|
+
@end.to_f - @start.to_f
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/swint/robot.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class Robot
|
9
|
+
|
10
|
+
attr_accessor :pos
|
11
|
+
|
12
|
+
attr_reader :speed, :sight, :power, :energy, :weight, :energy_left, :uri, :name, :owner
|
13
|
+
|
14
|
+
# --------------------------------------------------------------------------------
|
15
|
+
# --- stub
|
16
|
+
|
17
|
+
def initialize(uri, pos)
|
18
|
+
@uri = uri
|
19
|
+
@pos = pos
|
20
|
+
restore
|
21
|
+
end
|
22
|
+
|
23
|
+
def next(map)
|
24
|
+
end
|
25
|
+
|
26
|
+
def move
|
27
|
+
# check_direction(...)
|
28
|
+
end
|
29
|
+
|
30
|
+
def push
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_game(msg)
|
34
|
+
end
|
35
|
+
|
36
|
+
# --------------------------------------------------------------------------------
|
37
|
+
|
38
|
+
def is_valid?
|
39
|
+
(@speed + @sight + @power + @energy + @weight) == 22
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_direction(d)
|
43
|
+
unless (0..5).include?(d)
|
44
|
+
puts "#{@name}, what is this? '#{d}' is not a drection."
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
d
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_action(a)
|
51
|
+
unless [:do_nothing, :move_to, :push_object, :shout].include?(a)
|
52
|
+
puts "#{@name}, what is this? '#{a}' is not an action."
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
a
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
a = ["#{@name} (#{@owner})", @speed, @sight, @power, @weight, @energy]
|
60
|
+
"%-30s [sp: % 2s, si: % 2s, po: % 2s, we: % 2s, en: % 2s]" % a
|
61
|
+
end
|
62
|
+
|
63
|
+
def use_energy?
|
64
|
+
return false unless has_energy?
|
65
|
+
@energy_left -= 1
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_energy?
|
70
|
+
@energy_left>0
|
71
|
+
end
|
72
|
+
|
73
|
+
def restore
|
74
|
+
@energy_left = @energy
|
75
|
+
end
|
76
|
+
|
77
|
+
def calculate_view(map)
|
78
|
+
|
79
|
+
# A centered hexagonal number, or hex number, is a centered figurate
|
80
|
+
# number that represents a hexagon with a dot in the center and all
|
81
|
+
# other dots surrounding the center dot in a hexagonal lattice.
|
82
|
+
# 1, 7, 19, 37, 61, 91, 127, 169, 217, 271, 331, 397, 469, 547, 631, 721, 817, 919
|
83
|
+
|
84
|
+
# relative directions
|
85
|
+
reld = [2, 3, 4, 5, 0, 1]
|
86
|
+
|
87
|
+
data = []
|
88
|
+
cpos = pos.clone # that was tough!
|
89
|
+
|
90
|
+
### stef's version
|
91
|
+
|
92
|
+
sight.times do |depth|
|
93
|
+
cpos.add!(DIRV[0])
|
94
|
+
data << map.state_of_field(cpos)
|
95
|
+
5.times do |dir|
|
96
|
+
(depth+1).times do |i|
|
97
|
+
cpos.add!(DIRV[reld[dir]])
|
98
|
+
data << map.state_of_field(cpos)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
depth.times do |i|
|
102
|
+
cpos.add!(DIRV[reld[5]])
|
103
|
+
data << map.state_of_field(cpos)
|
104
|
+
end
|
105
|
+
cpos.add!(DIRV[1])
|
106
|
+
end
|
107
|
+
|
108
|
+
### sight.times do |depth|
|
109
|
+
### cpos.add!(DIRV[0])
|
110
|
+
### data << map.state_of_field(cpos)
|
111
|
+
### 6.times do |dir|
|
112
|
+
### (depth+1).times do |i|
|
113
|
+
### cpos.add!(DIRV[reld[dir]])
|
114
|
+
### data << map.state_of_field(cpos)
|
115
|
+
### end
|
116
|
+
### end
|
117
|
+
### end
|
118
|
+
|
119
|
+
data
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
module Swint
|
7
|
+
|
8
|
+
class XmlrpcRobot < AbstractRobot
|
9
|
+
|
10
|
+
attr_accessor :pos
|
11
|
+
|
12
|
+
attr_reader :speed, :sight, :power, :energy, :weight, :energy_left, :uri, :name, :owner
|
13
|
+
|
14
|
+
def initialize(uri, pos)
|
15
|
+
@uri = uri
|
16
|
+
@server = XMLRPC::Client.new2(@uri)
|
17
|
+
@gameid = @server.call('start_game')
|
18
|
+
@speed = @server.call('get_speed', @gameid)
|
19
|
+
@sight = @server.call('get_sight', @gameid)
|
20
|
+
@power = @server.call('get_power', @gameid)
|
21
|
+
@energy = @server.call('get_energy', @gameid)
|
22
|
+
@weight = @server.call('get_weight', @gameid)
|
23
|
+
@name = @server.call('get_name', @gameid)
|
24
|
+
@owner = @server.call('get_owner', @gameid)
|
25
|
+
@pos = pos
|
26
|
+
restore
|
27
|
+
end
|
28
|
+
|
29
|
+
def next(map)
|
30
|
+
check_action(@server.call('next', @gameid, calculate_view(map)).to_sym)
|
31
|
+
end
|
32
|
+
|
33
|
+
def move
|
34
|
+
check_direction(@server.call('move', @gameid))
|
35
|
+
end
|
36
|
+
|
37
|
+
def push
|
38
|
+
check_direction(@server.call('push', @gameid))
|
39
|
+
end
|
40
|
+
|
41
|
+
def end_game(msg)
|
42
|
+
@server.call('end_game', @gameid, msg)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#-*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# (c) 2008-01-07 Philipp Hofmann <phil@s126.de>
|
5
|
+
|
6
|
+
class Array
|
7
|
+
|
8
|
+
def add(a)
|
9
|
+
n = []
|
10
|
+
each_index { |i| n << (self[i] + a[i]) }
|
11
|
+
n
|
12
|
+
end
|
13
|
+
|
14
|
+
def add!(a)
|
15
|
+
replace(add(a))
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.5"
|
5
|
+
platform: ""
|
6
|
+
authors:
|
7
|
+
- Philipp Hofmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-01-20 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: a console client for the swarm intelligence programming game
|
17
|
+
email: phil @nospam@ branch14.org
|
18
|
+
executables:
|
19
|
+
- swint
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENSE
|
25
|
+
- CHANGELOG
|
26
|
+
files:
|
27
|
+
- lib/swint/field.rb
|
28
|
+
- lib/swint/game.rb
|
29
|
+
- lib/swint/map.rb
|
30
|
+
- lib/swint/robot.rb
|
31
|
+
- lib/swint/result.rb
|
32
|
+
- lib/swint/xmlrpc_robot.rb
|
33
|
+
- lib/swint/_constants.rb
|
34
|
+
- lib/swint/class_robot.rb
|
35
|
+
- lib/swint/abstract_robot.rb
|
36
|
+
- lib/swint_basics/array.rb
|
37
|
+
- lib/swint_basics/hash.rb
|
38
|
+
- bin/swint
|
39
|
+
- Rakefile
|
40
|
+
- CHANGELOG
|
41
|
+
- README
|
42
|
+
- LICENSE
|
43
|
+
has_rdoc: false
|
44
|
+
homepage: http://branch14.org/swint/
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: swint
|
65
|
+
rubygems_version: 0.9.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: a console client for the swarm intelligence programming game
|
69
|
+
test_files: []
|
70
|
+
|