scuby-wars 0.2.0

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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ /pkg/
2
+ /example_bots/.bundle/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Galaxy Cats IT Consulting
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.rdoc ADDED
@@ -0,0 +1,48 @@
1
+ = scuby-wars
2
+
3
+ Scuby-Wars is a little game where you have to implement your own AI-bots who will fight on a server against each other.
4
+
5
+ == How to write your own Bot
6
+
7
+ You have to implement a class which inherits from ScubyWars::Client
8
+
9
+ class AndisBot < ScubyWars::Client
10
+ end
11
+
12
+ now you have to implement on method called think
13
+
14
+ class AndisBot < ScubyWars::Client
15
+
16
+ def think
17
+ # do your intelligent stuff here
18
+ end
19
+
20
+ end
21
+
22
+ in your instance you can access the attribute world which has all informations about the world. And there are several methods you can call to control your bot:
23
+
24
+ run
25
+ stop
26
+ fire
27
+ cease_fire
28
+ turn_left
29
+ turn_right
30
+ stop_turning
31
+
32
+ == Connect your bot
33
+
34
+ YourBot.new("server.address:port", "YourName").join()
35
+
36
+ == Note on Patches/Pull Requests
37
+
38
+ * Fork the project.
39
+ * Make your feature addition or bug fix.
40
+ * Add tests for it. This is important so I don't break it in a
41
+ future version unintentionally.
42
+ * Commit, do not mess with rakefile, version, or history.
43
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
44
+ * Send me a pull request. Bonus points for topic branches.
45
+
46
+ == Copyright
47
+
48
+ Copyright (c) 2011 Andi Bade. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "scuby-wars"
8
+ gem.summary = %Q{Library for programming little AI-Bots, fighting against each other}
9
+ gem.description = %Q{Library for programming little AI-Bots, fighting against each other}
10
+ gem.email = "andi@galaxycats.com"
11
+ gem.homepage = "http://github.com/galaxycats/scuby-wars"
12
+ gem.authors = ["Andi Bade", "Dirk Breuer", "Sebastian Cohnen"]
13
+ gem.add_dependency "yajl-ruby", ">= 0.7.8"
14
+ gem.add_dependency "httparty", ">= 0.6.1"
15
+ gem.add_dependency "i18n", ">= 0.5.0"
16
+ gem.add_dependency "activesupport", ">= 3.0.3"
17
+ # gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/test_*.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ begin
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ end
39
+ rescue LoadError
40
+ task :rcov do
41
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+ end
44
+
45
+ task :test => :check_dependencies
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "scuby-wars #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,2 @@
1
+ # gem "scuby-wars", :git => "git://github.com/galaxycats/scuby-wars.git"
2
+ gem "scuby-wars", :path => "/Users/andi/galaxycats/projects/tondorf/scuby-wars"
@@ -0,0 +1,7 @@
1
+ = Examples
2
+
3
+ == Executing the examples
4
+
5
+ bundle install
6
+ bundle exec "irb -r chaos.rb"
7
+ >> Chaos.new("localhost:3000", "Chaos").join()
@@ -0,0 +1,43 @@
1
+ require "scuby-wars"
2
+
3
+ class Chaos < ScubyWars::Client
4
+
5
+ def think
6
+ change_turning
7
+ change_fireing
8
+ change_running
9
+ end
10
+
11
+ def change_turning
12
+ if self.turning?
13
+ self.stop_turning if rand(2) == 1
14
+ else
15
+ case rand(4)
16
+ when 0
17
+ self.turn_left
18
+ when 1
19
+ self.turn_right
20
+ else
21
+ end
22
+ end
23
+ end
24
+
25
+ def change_fireing
26
+ if self.fireing?
27
+ self.stop_fireing if rand(4) == 1
28
+ else
29
+ self.fire if rand(4) == 1
30
+ end
31
+ end
32
+
33
+ def change_running
34
+ if self.running?
35
+ self.stop if rand(2) == 0
36
+ else
37
+ self.run if rand(4) < 4
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ # Chaos.new("localhost:3000", "Chaos").join()
@@ -0,0 +1,12 @@
1
+ require "scuby-wars"
2
+
3
+ class ShotAndRun < ScubyWars::Client
4
+
5
+ def think
6
+ self.fire unless self.fireing?
7
+ self.run unless self.running?
8
+ end
9
+
10
+ end
11
+
12
+ # ShotAndRun.new("localhost:3000", "ShotAndRun").join()
@@ -0,0 +1,10 @@
1
+ require 'yajl'
2
+ require 'yajl/http_stream'
3
+ require 'httparty'
4
+ require 'active_support/inflector'
5
+
6
+ module ScubyWars
7
+
8
+ end
9
+
10
+ require 'scuby_wars/client'
data/lib/scuby-wars.rb ADDED
@@ -0,0 +1 @@
1
+ require "scruby_wars"
@@ -0,0 +1,135 @@
1
+ module ScubyWars
2
+ class Client
3
+ include HTTParty
4
+
5
+ attr_accessor :world, :server
6
+
7
+ ##
8
+ # Example:
9
+ # player = ScubyWars::Client.join("localhost:3000", "player-name")
10
+ # player.stop!
11
+ # player.turn_left!
12
+ # player.run!
13
+ # player.fire!
14
+ def self.join(server, nick)
15
+ game = new(server, nick)
16
+ if block_given?
17
+ Yajl::HttpStream.get(URI.parse("http://#{server}/world")) do |world|
18
+ game.world = world
19
+ game.instance_eval(yield)
20
+ game.update_player
21
+ end
22
+ end
23
+ game
24
+ end
25
+
26
+ def initialize(server, nick)
27
+ @player = {:nick => nick, :actions => {:thrust => false, :turnLeft => false, :turnRight => false, :fire => false}}
28
+ @server = server
29
+ begin
30
+ self.class.post("http://#{@server}/players/#{@player[:nick]}")
31
+ rescue => e
32
+ puts "Could not connect to game-server"
33
+ raise e
34
+ end
35
+ end
36
+
37
+ def join
38
+ Yajl::HttpStream.get(URI.parse("http://#{server}/world")) do |world|
39
+ self.world = world
40
+ think
41
+ update_player
42
+ end
43
+ end
44
+
45
+ def run
46
+ @player[:actions][:thrust] = true
47
+ end
48
+
49
+ def running?
50
+ @player[:actions][:thrust]
51
+ end
52
+
53
+ def stop
54
+ @player[:actions][:thrust] = false
55
+ end
56
+
57
+ def turn_left
58
+ @player[:actions][:turnLeft] = true
59
+ @player[:actions][:turnRight] = false
60
+ end
61
+
62
+ def turning_left?
63
+ @player[:actions][:turnLeft]
64
+ end
65
+
66
+ def turn_right
67
+ @player[:actions][:turnLeft] = false
68
+ @player[:actions][:turnRight] = true
69
+ end
70
+
71
+ def turning_right?
72
+ @player[:actions][:turnRight]
73
+ end
74
+
75
+ def turning?
76
+ turning_left? || turning_right?
77
+ end
78
+
79
+ def stop_turning
80
+ @player[:actions][:turnLeft] = false
81
+ @player[:actions][:turnRight] = false
82
+ end
83
+
84
+ def fire
85
+ @player[:actions][:fire] = true
86
+ end
87
+
88
+ def fireing?
89
+ @player[:actions][:fire]
90
+ end
91
+
92
+ def cease_fire
93
+ @player[:actions][:fire] = false
94
+ end
95
+
96
+ def stop_fireing
97
+ cease_fire
98
+ end
99
+
100
+ %w(run stop turn_left turn_right stop_turning fire cease_fire).each do |meth_name|
101
+ define_method "#{meth_name}!" do
102
+ send(meth_name)
103
+ update_player
104
+ end
105
+ end
106
+
107
+ def update_player
108
+ puts "Sending #{@player.inspect} to http://#{@server}/players/#{@player[:nick]}"
109
+ self.class.put("http://#{@server}/players/#{@player[:nick]}", :body => Yajl::Encoder.encode(@player))
110
+ end
111
+ end
112
+ end
113
+
114
+
115
+
116
+ # require "grashopper"
117
+
118
+ # Grasshopper.join("localhost:3000", "andi1") do
119
+ # world
120
+ #
121
+ # run
122
+ # # stop!
123
+ # #
124
+ # turn_left
125
+ # # turn_right!
126
+ # # stop_turning!
127
+ # #
128
+ # # shoot!
129
+ # # cease_fire!
130
+ # end
131
+
132
+ # p = Grasshopper.join("localhost:3000", "andi2")
133
+ # p.run!
134
+ # p.stop!
135
+ # p.turn_right!
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'yajl'
3
+ require 'yajl/http_stream'
4
+
5
+ require 'pp'
6
+
7
+ Yajl::HttpStream.get(URI.parse("http://localhost:3000/world")) do |frame|
8
+ pp frame
9
+ end
@@ -0,0 +1,89 @@
1
+ var app = require('express').createServer(),
2
+ io = require('socket.io'), // for npm, otherwise use require('./path/to/socket.io')
3
+ sys = require('sys'),
4
+ express = require('express');
5
+ grasshopper = require('./lib/grasshopper');
6
+
7
+ var game = grasshopper.getGame();
8
+ var socket = io.listen(app);
9
+ var knownClients = [];
10
+
11
+ app.configure(function() {
12
+ app.use(app.router);
13
+ app.use(express.staticProvider(__dirname + '/public'));
14
+ app.set("views", __dirname + "/views");
15
+ app.set('view engine', 'ejs');
16
+ });
17
+
18
+ app.get("/", function(req, res) {
19
+ res.render("index", { "layout" : false });
20
+ });
21
+
22
+ app.get("/world", function(req, res) {
23
+ res.writeHead(200, { "Content-Type" : "application/json"});
24
+ sys.puts("Registered client to consume world data.");
25
+ knownClients.push(res);
26
+ });
27
+
28
+ app.post("/players/:name", function(req, res) {
29
+ try {
30
+ var player = game.addPlayer({ip: req.headers.ip, name: req.params.name})
31
+ sys.puts("Added player: " + player.name);
32
+ res.writeHead(200, { "Content-Type" : "application/json"});
33
+ res.write(JSON.stringify({ "ok" : true }));
34
+ } catch(m) {
35
+ sys.puts(m);
36
+ res.writeHead(409, { "Content-Type" : "application/json"});
37
+ res.write(JSON.stringify({ "error" : m }));
38
+ }
39
+ res.end();
40
+ });
41
+
42
+ app.put("/players/:name", function(req, res) {
43
+ var player = game.findPlayer(req.params.name);
44
+
45
+ if (player) {
46
+ var body = "";
47
+ req.on("data", function(data) {
48
+ body += data;
49
+ });
50
+
51
+ req.on("end", function() {
52
+ actions = JSON.parse(body).actions;
53
+ player.newActions(actions);
54
+ res.writeHead(200, { "Content-Type" : "application/json"});
55
+ res.write(JSON.stringify({ "ok" : true }));
56
+ res.end();
57
+ });
58
+ } else {
59
+ console.log("Player with name '" + req.params.name + "' couldn't be found.");
60
+ res.writeHead(404, { "Content-Type" : "application/json"});
61
+ res.write(JSON.stringify({ "error" : "player not found: " + req.params.name }));
62
+ res.end();
63
+ };
64
+ });
65
+
66
+ app.post("/reset", function(req, res) {
67
+ game = grasshopper.resetGame();
68
+ res.writeHead(200, { "Content-Type" : "application/json" });
69
+ res.write(JSON.stringify({ "ok" : true }));
70
+ res.end();
71
+ });
72
+
73
+ app.listen(3000);
74
+
75
+ socket.on('connection', function(client) {
76
+ sys.puts("A new spectator just connected. Welcome it!")
77
+
78
+ client.on('message', function(message) {});
79
+ client.on('disconnect', function() {});
80
+ });
81
+
82
+ setInterval(function() {
83
+ game.turn();
84
+ socket.broadcast(game.world);
85
+ var jsonWorld = JSON.stringify(game.world);
86
+ knownClients.forEach(function(res) {
87
+ res.write(jsonWorld);
88
+ });
89
+ }, grasshopper.WorldDefs.serverTick);