-
-
Save Hanmac/46aa0ecda5d117ed061d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "test/unit" | |
require "observer" | |
require "turn/autorun" | |
module Eventable | |
include Observable | |
# Alternative method to register an observer. In | |
# contrast to Observable#add_observer, which requires | |
# you to construct an object responding to :update or | |
# specify another symbol, this method takes a block | |
# that will be called when the observed object emmits | |
# an event of the requested type. | |
# == Parameters | |
# [target_event (nil)] | |
# Only fire the callback if the observed object issued | |
# an event of this type. If this is +nil+, the callback | |
# is always fired when the observed object changes. | |
def observe(target_event = nil) | |
callback = lambda do |event, emitter, info| | |
yield(event, emitter, info) if !target_event || event == target_event | |
end | |
add_observer(callback, :call) | |
end | |
def observe_value(event,meth) | |
@__auto_observes ||= [] | |
@__auto_observes << [event,meth] | |
#yield | |
#p send(meth) != v | |
#changed | |
#notify_observers(event) | |
end | |
def auto_observe | |
@__auto_observes ||= [] | |
temp = @__auto_observes.map{|event,meth|send(meth)} | |
yield | |
temp2 = @__auto_observes.map{|event,meth|send(meth)} | |
@__auto_observes.each.with_index {|(event,meth),index| | |
changed if temp[index] != temp2[index] | |
notify_observers(event) | |
} | |
end | |
# Works the same way as Observable#notify_observers, but | |
# automatically inserts +self+ as the second argument to | |
# the +super+ call so that observers know who called. | |
# +info+ is a hash that will be passed through to the observers. | |
def notify_observers(event, info = {}) | |
super(event, self, info) | |
end | |
end | |
def overwrite(meth,&block) | |
old = instance_method(meth) | |
#we need to call super first | |
if old.owner != self | |
define_method(meth) do |*args, &b| | |
super(*args, &b) | |
instance_exec(*args,&block) | |
end | |
else | |
define_method(meth) do |*args, &b| | |
old.bind(self).call(*args, &b) | |
instance_exec(*args,&block) | |
end | |
end | |
end | |
def overwrite_hash_sum(meth,&block) | |
old = instance_method(meth) | |
define_method(meth) do |*args, &b| | |
temp = self.instance_exec(*args,&block) | |
temp = (temp.is_a?(Array) ? temp : [temp]) | |
temp.inject(old.bind(self).call(*args, &b)) {|el,memo| | |
memo.merge(el) {|k,o,n| Array(o) + Array(n)} | |
} | |
end | |
end | |
def overwrite_hash_product(meth,&block) | |
unless method_defined?(meth) | |
define_method(meth) do |*args, &b| | |
return Hash.new(1.0) | |
end | |
end | |
old = instance_method(meth) | |
define_method(meth) do |*args, &b| | |
temp = self.instance_exec(*args,&block) | |
temp = (temp.is_a?(Array) ? temp : [temp]) | |
temp.inject(old.bind(self).call(*args, &b)) {|el,memo| | |
memo.merge(el) {|k,o,n| o * n} | |
} | |
end | |
end | |
module RPG;end | |
module Game;end | |
#state | |
module RPG | |
class State | |
@instances = {} | |
attr_accessor :name | |
attr_reader :states_chance | |
def initialize(name) | |
@name = name | |
@states_chance = Hash.new(1.0) | |
self.class.instances[@name] = self | |
end | |
class << self | |
attr_reader :instances | |
def [](key) | |
@instances[key] | |
end | |
end | |
end | |
end | |
module Game | |
class State | |
attr_reader :name | |
def initialize(name) | |
@name = name | |
#cs_init | |
end | |
def states_chance | |
RPG::State[@name].states_chance | |
end | |
end | |
end | |
#baseitem | |
module RPG | |
class BaseItem | |
attr_accessor :name | |
def initialize(name) | |
@name = name | |
self.class.instances[@name] = self | |
end | |
class << self | |
#attr_reader :instances | |
def instances | |
return @instances ||= {} | |
end | |
def [](key) | |
(@instances ||= {})[key] | |
end | |
end | |
end | |
end | |
module Game | |
class BaseItem | |
attr_reader :name | |
def initialize(name) | |
@name = name | |
end | |
end | |
end | |
#equip + stats | |
module RPG | |
module EquipableItem | |
attr_accessor :states_chance,:auto_states,:require_states | |
#private | |
def initialize(*) | |
super | |
@auto_states = [] | |
@require_states = [] | |
@states_chance = Hash.new(1.0) | |
end | |
end | |
end | |
module Game | |
module EquipableItem | |
attr_reader :auto_states | |
#private | |
def initialize(*) | |
super | |
@auto_states = {} | |
rpg.auto_states.each{|n| @auto_states[n] = State.new(n) } | |
end | |
def states_chance | |
return rpg.states_chance | |
end | |
end | |
end | |
#weapon | |
module RPG | |
class Weapon < BaseItem | |
include EquipableItem | |
end | |
end | |
module Game | |
class Weapon < BaseItem | |
include EquipableItem | |
def rpg | |
RPG::Weapon[@name] | |
end | |
end | |
end | |
#skills | |
module RPG | |
class Skill < BaseItem | |
end | |
end | |
module Game | |
class Skill < BaseItem | |
def rpg | |
RPG::Skill[@name] | |
end | |
end | |
end | |
module Game | |
class Battler | |
include Eventable | |
attr_reader :name | |
def initialize(name) | |
@name = name | |
@sockets = {} | |
end | |
def equips | |
return {} if @sockets.nil? | |
return @sockets.dup.delete_if{|k,v|v.nil?} | |
end | |
def equip(slot,item) | |
# cs_unequiped(slot,@sockets[slot]) unless @sockets[slot].nil? | |
auto_observe { | |
@sockets[slot]=item | |
changed | |
notify_observers(:equiped,:slot => slot, :item => item) | |
} | |
# cs_equiped(slot,item) | |
return self | |
end | |
end | |
end | |
#actor | |
module RPG | |
class Actor | |
attr_accessor :name | |
def initialize(name) | |
@name = name | |
self.class.instances[@name] = self | |
end | |
class << self | |
#attr_reader :instances | |
def instances | |
return @instances ||= {} | |
end | |
def [](key) | |
(@instances ||= {})[key] | |
end | |
end | |
end | |
end | |
module Game | |
class Actor < Battler | |
end | |
end | |
#enemy | |
module RPG | |
class Enemy | |
attr_accessor :name | |
def initialize(name) | |
@name = name | |
self.class.instances[@name] = self | |
end | |
class << self | |
#attr_reader :instances | |
def instances | |
return @instances ||= {} | |
end | |
def [](key) | |
(@instances ||= {})[key] | |
end | |
end | |
end | |
end | |
module Game | |
class Enemy < Battler | |
def rpg | |
return RPG::Enemy[@name] | |
end | |
end | |
end | |
#Battler + States | |
module Game | |
class Battler | |
attr_reader :states | |
overwrite(:initialize) { | |
@states = Hash.new([]) | |
observe_value(:states_chance_changed,:states_chance) | |
} | |
overwrite_hash_product(:states_chance) { states.values.flatten.map(&:states_chance) } | |
def add_state(key) | |
temp = State.new(key) | |
#if(@states[k].size > temp.rpg.stocks) | |
# @states[k].shift | |
#end | |
#states_cancel | |
#temp.rpg.states_cancel.each {|c| @states[c].each{remove_state(c)} } | |
auto_observe { | |
@states[key] += [temp] | |
changed | |
notify_observers(:state_added, :state => temp) | |
} | |
#cs_add_state(k) | |
return temp | |
end | |
def remove_state(key) | |
unless(@states[key].empty?) | |
auto_observe { | |
temp = @states[key].shift | |
changed | |
notify_observers(:state_removed, :state => temp) | |
} | |
return temp | |
else | |
return nil | |
end | |
end | |
end | |
end | |
#Battler + States + equip | |
module Game | |
class Battler | |
overwrite_hash_sum(:states) { equips.each_value.flat_map(&:auto_states) } | |
overwrite_hash_product(:states_chance) { equips.values.flatten.map(&:states_chance) } | |
end | |
end | |
#Actorclass | |
module RPG | |
class ActorClass | |
attr_accessor :name | |
def initialize(name) | |
@name = name | |
self.class.instances[@name] = self | |
end | |
class << self | |
#attr_reader :instances | |
def instances | |
return @instances ||= {} | |
end | |
def [](key) | |
(@instances ||= {})[key] | |
end | |
end | |
end | |
end | |
module Game | |
class ActorClass | |
attr_reader :name | |
attr_reader :actor | |
attr_reader :level | |
def initialize(name,actor) | |
@name = name | |
@actor = actor | |
@level = 0 | |
end | |
def rpg | |
RPG::ActorClass[@name] | |
end | |
end | |
class Actor | |
attr_accessor :actorclasses | |
attr_accessor :removed_actorclasses | |
overwrite(:initialize) { | |
@actorclasses = {} | |
@removed_actorclasses = {} | |
} | |
def add_actorclass(k) | |
if @removed_actorclasses.include?(k) | |
@actorclasses[k] = @removed_actorclasses[k] | |
@removed_actorclasses.delete(k) | |
elsif !@actorclasses.include?(k) | |
@actorclasses[k] = create_actorclass(k) | |
end | |
#cs_add_actorclass(k) | |
return self | |
end | |
def remove_actorclass(k) | |
if @actorclasses.include?(k) | |
@removed_actorclasses[k] = @actorclasses[k] | |
@actorclasses.delete(k) | |
#cs_remove_actorclass(k) | |
end | |
return self | |
end | |
#private | |
def create_actorclass(k) | |
@actorclasses[k] = ActorClass.new(k,@name) | |
end | |
end | |
end | |
#actorclass + states | |
module RPG | |
class ActorClass | |
attr_accessor :states_chance,:auto_states | |
overwrite(:initialize) { | |
@auto_states = [] | |
@states_chance = Hash.new(1.0) | |
} | |
end | |
end | |
module Game | |
class ActorClass | |
attr_reader :auto_states | |
overwrite(:initialize) { | |
@auto_states = {} | |
rpg.auto_states.each{|n| @auto_states[n] = State.new(n) } | |
} | |
def states_chance | |
return rpg.states_chance | |
end | |
end | |
class Actor | |
overwrite_hash_sum(:states) { actorclasses.each_value.flat_map(&:auto_states) } | |
overwrite_hash_product(:states_chance) { actorclasses.values.flatten.map(&:states_chance) } | |
end | |
end | |
#battler + skills | |
module Game | |
class Battler | |
attr_reader :skills | |
overwrite(:initialize) { @skills = Hash.new([]) } | |
def add_skill(k) | |
temp = Skill.new(k) | |
@skills[k] += [temp] | |
changed | |
notify_observers(:skill_added, :skill => temp) | |
return temp | |
end | |
def remove_skill(k) | |
unless(@skills[k].empty?) | |
temp = @skills[k].shift | |
changed | |
notify_observers(:skill_removed, :skill => temp) | |
return temp | |
else | |
return nil | |
end | |
end | |
end | |
end | |
#enemy + skills | |
module RPG | |
class Enemy | |
attr_accessor :skills | |
overwrite(:initialize) { @skills = [] } | |
end | |
end | |
module Game | |
class Enemy | |
#overwrite_hash_sum(:skills) { actorclasses.each_value.flat_map(&:auto_states) } | |
overwrite(:initialize) { rpg.skills.each{|s|add_skill(s)} } | |
end | |
end | |
class OverwriteTest < Test::Unit::TestCase | |
def setup | |
s=RPG::State.new(:burn) | |
s.states_chance[:freeze] = 0.5 | |
w=RPG::Weapon.new(:sword) | |
w.auto_states << :burn | |
st=RPG::Weapon.new(:staff) | |
st.states_chance[:freeze] = 0.5 | |
warrior=RPG::ActorClass.new(:warrior) | |
warrior.states_chance[:freeze] = 0.5 | |
end | |
def test_states | |
#init rpg stuff | |
b = Game::Actor.new(:alex) | |
b.observe(:state_added) {|_,_,info| throw :sta} | |
b.observe(:state_removed) {|_,_,info| throw :str} | |
b.observe(:equiped) {|_,_,info| throw :eq} | |
# b.observe(:states_chance_changed) {|_,_,info| p "yeah auto works" } | |
assert_equal({},b.states) | |
assert_equal(1,b.states_chance[:freeze]) | |
#assert_throws(:stcc){ | |
#b.observe_value(:states_chance_changed,:states_chance) do | |
#end | |
#} | |
assert_throws(:sta){b.add_state(:burn)} | |
assert_equal(1,b.states[:burn].size) | |
assert_equal(0.5,b.states_chance[:freeze]) | |
assert_throws(:str){b.remove_state(:burn)} | |
assert_equal({:burn=>[]},b.states) | |
assert_equal(1,b.states_chance[:freeze]) | |
assert_throws(:sta){b.add_state(:burn)} | |
sword = Game::Weapon.new(:sword) | |
staff = Game::Weapon.new(:staff) | |
#sword.auto_states << Game::State.new(:burn) | |
assert_throws(:eq){ b.equip :hand, sword} | |
assert_equal(2,b.states[:burn].size) | |
assert_equal(0.25,b.states_chance[:freeze]) | |
assert_throws(:eq){b.equip :hand, nil} | |
assert_equal(1,b.states[:burn].size) | |
assert_equal(0.5,b.states_chance[:freeze]) | |
assert_throws(:eq){b.equip :hand, sword} | |
assert_equal(2,b.states[:burn].size) | |
assert_equal(0.25,b.states_chance[:freeze]) | |
assert_throws(:eq){b.equip :hand, staff} | |
assert_equal(1,b.states[:burn].size) | |
assert_equal(0.25,b.states_chance[:freeze]) | |
b.add_actorclass(:warrior) | |
assert_equal(1,b.states[:burn].size) | |
assert_equal(0.125,b.states_chance[:freeze]) | |
end | |
def test_changed_events | |
b = Game::Actor.new(:alex) | |
b.observe(:states_chance_changed) {|_,_,info| throw :stcc } | |
assert_throws(:stcc){b.add_state(:burn)} | |
assert_throws(:stcc){b.remove_state(:burn)} | |
sword = Game::Weapon.new(:sword) | |
staff = Game::Weapon.new(:staff) | |
#sword.auto_states << Game::State.new(:burn) | |
assert_throws(:stcc){ b.equip :hand, sword} | |
assert_throws(:stcc){b.equip :hand, nil} | |
assert_throws(:stcc){ b.equip :hand, staff} | |
assert_nothing_thrown(:stcc){ b.equip :hand, sword} | |
end | |
def test_skills | |
e = RPG::Enemy.new(:slime) | |
e.skills << :fireball | |
b = Game::Actor.new(:alex) | |
b.observe(:skill_added) {|_,_,info| throw :ska} | |
b.observe(:skill_removed) {|_,_,info| throw :skr} | |
assert_equal({},b.skills) | |
assert_equal(0,b.skills[:fireball].size) | |
assert_throws(:ska){b.add_skill(:fireball)} | |
assert_equal(1,b.skills[:fireball].size) | |
assert_throws(:skr){b.remove_skill(:fireball)} | |
assert_equal(0,b.skills[:fireball].size) | |
ge=Game::Enemy.new(:slime) | |
assert_equal(1,ge.skills[:fireball].size) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment