scuby-wars 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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);