Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: DanKnox/ruby-mmo
base: 54e34093b1
...
head fork: DanKnox/ruby-mmo
compare: 77570b15ab
  • 2 commits
  • 5 files changed
  • 1 commit comment
  • 1 contributor
View
3  Gemfile
@@ -1,3 +1,4 @@
source 'http://rubygems.org'
-gem 'debugger'
+gem 'debugger'
+gem 'rspec'
View
122 players/dank.rb
@@ -0,0 +1,122 @@
+(0..9).each do |n|
+ eval %(
+ module Dank#{n}
+ BOSS_DANGER_ZONE = 90
+ MINION_DANGER_ZONE = 20
+ ATTACKER_POOL = 5
+
+ def to_s
+ minion? ? "Minion" : "Dan Knox"
+ end
+
+ def move
+ prepare_friendlies if game_is_beginning?
+ promote_minion if boss_lacks_experience?
+ minion? ? rest_or_attack : command_and_control
+ end
+
+ def trade(command,target=nil)
+ case command
+ when :begin_game
+ @minion = true
+ @game_underway = true
+ when :set_target
+ @target = target
+ when :set_boss
+ @minion = false
+ end
+ end
+
+ protected
+
+ def rest_or_attack
+ @target = available_monsters.sample if @target.nil?
+ dangerous_health? ? [:rest] : [:attack,@target]
+ end
+
+ def command_and_control
+ @target = @next_target
+ set_attack_targets
+ rest_or_attack
+ end
+
+ def set_attack_targets
+ @current_friends = friends
+ attackers = ATTACKER_POOL
+
+ friends.each_with_index do |friend,index|
+ new_target = index <= attackers ? strongest_enemies[0] : strongest_enemies[1]
+ friend.trade( :set_target, new_target )
+ end
+
+ @next_target = strongest_enemies[0]
+ end
+
+ def aggregrate_strength
+ @current_friends.inject(0) { |sum,friend| sum + friend.stats[:strength] }
+ end
+
+ def dangerous_health?
+ boss? ?
+ (stats[:health] <= BOSS_DANGER_ZONE) :
+ (stats[:health] <= MINION_DANGER_ZONE)
+ end
+
+ def target_set?
+ @target
+ end
+
+ def promote_minion
+ @minion = true
+ most_experienced_minion.trade(:set_boss)
+ end
+
+ def boss_lacks_experience?
+ stats[:experience] < most_experienced_minion.stats[:experience]
+ end
+
+ def prepare_friendlies
+ @minion = false
+ friends.each do |friend|
+ friend.trade(:begin_game)
+ end
+ end
+
+ def friends
+ Game.world[:players].select { |p| p.to_s =~ /(Minion|Dan Knox)/ && p != self }
+ end
+
+ def enemies
+ Game.world[:players].select { |p| p.alive }.reject { |p| friends.include?(p) or p == self }
+ end
+
+ def strongest_enemies
+ enemies.sort { |a,b| b.stats[:experience] <=> a.stats[:experience] }
+ end
+
+ def most_experienced_minion
+ friends.sort_by { |m| m.stats[:experience] }.last
+ end
+
+ def available_monsters
+ Game.world[:players].select { |player| monsters.include?(player.to_s) && player.alive }
+ end
+
+ def monsters
+ ["rat"]
+ end
+
+ def minion?
+ @minion
+ end
+
+ def boss?
+ !@minion
+ end
+
+ def game_is_beginning?
+ !@game_underway
+ end
+ end
+ )
+end
View
146 spec/players/dank_spec.rb
@@ -0,0 +1,146 @@
+require 'spec_helper'
+
+def load_players_for_dan
+ test_mod = mock('Dank0')
+ @boss = create_player_for_module(Dank0)
+ @minions = []
+ (1..9).each do |n|
+ mod = Object::const_get("Dank#{n}")
+ @minions << create_player_for_module(mod)
+ end
+ @enemies = []
+ RSpec.configuration.mock_player_count.each do |n|
+ mod = Object::const_get("PlayerMock#{n}")
+ @enemies << create_player_for_module(mod)
+ end
+end
+
+describe Dank0, "The Boss" do
+ before(:each) { start_game and load_players_for_dan and silence_output }
+
+ describe "#to_s" do
+ it "should have the correct name for the boss" do
+ @boss.to_s.should == "Dan Knox"
+ end
+ end
+
+ describe "minion?" do
+ it "should return false after the first round" do
+ commence_round
+ @boss.send(:minion?).should be_false
+ end
+ end
+
+ describe "#prepare_friendlies" do
+ it "should only be called during the first round" do
+ @boss.should_receive(:prepare_friendlies).once
+ 2.times { commence_round }
+ end
+
+ it "should tell the minions that the game is underway" do
+ Player.any_instance.stub(:trade)
+ @minions.first.should_receive(:trade).with(:begin_game).once
+ commence_round
+ end
+ end
+
+ describe "#set_attack_targets" do
+ before(:each) do
+ 5.times { commence_round }
+ end
+
+ it "should tell the first five minions to attack the most experienced enemy" do
+ target = @enemies.sort_by { |e| e.stats[:experience] }.last
+ @minions.first.should_receive(:trade) do |command,new_target|
+ new_target.stats[:experience].should == target.stats[:experience]
+ end
+ @boss.send(:set_attack_targets)
+ end
+
+ it "should tell the remaining minions to attack the second most experienced enemy" do
+ target = @enemies.sort_by { |e| e.stats[:experience] }[-2]
+ @minions.first.should_receive(:trade) do |command,new_target|
+ new_target.stats[:experience].should == target.stats[:experience]
+ end
+ @boss.send(:set_attack_targets)
+ end
+ end
+
+ context "during the end game" do
+ before(:each) do
+ 100.times { commence_round }
+ end
+
+ it "Dan Knox should always be the winner!" do
+ proxies = @game.proxies
+ winner = proxies.inject(proxies[0]) {|max, item| item.stats[:experience] > max.stats[:experience] ? item : max }
+ winner.to_s.should =~ /Dan Knox/
+ end
+ end
+end
+
+describe "Dank(1..9)", "The Minions" do
+ before(:each) { start_game and load_players_for_dan and silence_output }
+
+ describe "#to_s" do
+ it "should have the correct name for the minions after the first round" do
+ commence_round
+ @minions.each { |m| m.to_s.should == "Minion" }
+ end
+ end
+
+ describe "minion?" do
+ it "should return true after the first round" do
+ commence_round
+ @minions.each { |m| m.send(:minion?).should be_true }
+ end
+ end
+
+ describe "#prepare_friendlies" do
+ it "should never be called" do
+ @minions.each { |minion| minion.should_not_receive(:prepare_friendlies) }
+ 2.times { commence_round }
+ end
+ end
+
+ describe "#promote_minion" do
+ before(:each) do
+ @minion = @minions.first
+ end
+
+ it "should not trigger if boss is most experienced" do
+ @minion.stub(:boss_lacks_experience?).and_return(false)
+ @minion.should_not_receive(:promote_minion)
+ commence_round
+ end
+
+ it "should trigger when boss falls behind a minion in experience" do
+ @minion.stub(:boss_lacks_experience?).and_return(true)
+ @minion.should_receive(:promote_minion)
+ commence_round
+ end
+
+ it "should set the most experienced minion as the new boss" do
+ commence_round
+ new_boss = @minions.sort_by { |m| m.stats[:experience] }.last
+ @minion.send(:promote_minion)
+ new_boss.minion?.should be_false
+ end
+ end
+
+ describe "#boss_lacks_experience?" do
+ before(:each) { commence_round }
+
+ it "should return true when a minion has more experience than the boss" do
+ minion = @minions.first
+ minion.stub(:stats).and_return({ experience: 1000 })
+ @boss.stub(:stats).and_return({ experience: 0 })
+ @boss.send(:boss_lacks_experience?).should be_true
+ end
+
+ it "should return false when the boss has the highest experience level" do
+ @boss.stub(:stats).and_return({ experience: 10000 })
+ @boss.send(:boss_lacks_experience?).should be_false
+ end
+ end
+end
View
37 spec/spec_helper.rb
@@ -0,0 +1,37 @@
+[:engine,:monsters].each do |dir|
+ Dir[File.expand_path("../../#{dir}/*.rb",__FILE__)].each {|f| require f}
+end
+
+require File.expand_path("../../players/dank",__FILE__)
+
+RSpec.configure do |config|
+ config.treat_symbols_as_metadata_keys_with_true_values = true
+
+ config.add_setting :mock_player_count
+ config.mock_player_count = (0..5)
+end
+
+Dir[File.expand_path("../support/*.rb",__FILE__)].each {|f| require f}
+
+def start_game
+ @game = Game.new
+end
+
+def create_player_for_module(mod)
+ player = Player.new
+ @game.players << player
+ p = PlayerProxy.new(player)
+ p.extend mod
+ player.proxy = p
+ @game.proxies << p
+ p
+end
+
+def commence_round
+ @game.round(1)
+end
+
+def silence_output
+ @original_stdout = $stdout
+ $stdout = File.new('/dev/null', 'w')
+end
View
12 spec/support/player_mock.rb
@@ -0,0 +1,12 @@
+RSpec.configuration.mock_player_count.each do |n|
+ eval %(
+ module PlayerMock#{n}
+ def to_s
+ "Mock Player"
+ end
+ def move
+ [:rest]
+ end
+ end
+ )
+end

Showing you all comments on commits in this comparison.

@davidk01

Not sure if this should be allowed. There is a simple way to thwart you strategy though.

Something went wrong with that request. Please try again.