14. My Epic Mode Solution
● An AI logic that pass intermediate epic mode
with all-S rank
● Three implementation styles:
● Naive Solution
● Pure-OO Solution
● Metaprogramming&DSL Solution
15. Naive Solution
DIRS.each do |dir|
if @warrior.feel(dir).ticking?
@warrior.rescue!(dir)
return
end
end
return if walk_to_ticking!
DIRS.each do |dir|
if should_detonate?(dir)
detonate!(dir)
return
end
end
DIRS.each do |dir|
if @warrior.feel(dir).enemy?
@warrior.attack!(dir)
return
end
end
DIRS.each do |dir|
if @warrior.feel(dir).captive?
@warrior.rescue!(dir)
return
end
end
walk!(direction_of_stairs)
Demo!
17. Metaprogramming&DSL Solution
● Today we won't focus on how to do
metaprogramming and create a DSL
● We focus on how metaprogramming & DSL
make our life easier
21. We use attr_accessor everyday
class Warrior
attr_accessor :health
end
w = Warrior.new
w.health = 95
puts w.health
22. What is attr_accessor?
class Warrior class Warrior
attr_accessor :health def health
end @health
end
w = Warrior.new def health=(val)
w.health = 95 @health = val
puts w.health end
end
w = Warrior.new
w.health = 59
puts w.health
attr_acccessor is a METHOD!
23. Getter/Setter in Java
class Warrior
{
public void setHealth(int val)
{
health = val;
}
public int getHealth()
{
return health;
}
private int health;
}
public class AttrAccessor
{
public static void main(String[] args)
{
Warrior s = new Warrior();
s.setHealth(95);
System.out.println("Health = " + s.getHealth());
}
}
24. Delegation
class Player
def hurt?
return false unless @last_health
return @warrior.health < @last_health
end
def play_turn(warrior)
@warrior = warrior
if @warrior.feel.captive?
@warrior.rescue!
elsif !@warrior.feel.empty?
@warrior.attack!
elsif @warrior.health == 20 || hurt?
@warrior.walk!
else
@warrior.rest!
end
@last_health = @warrior.health
end
end
25. Delegation
class Player class Player
def hurt? def hurt?
return false unless @last_health return false unless @last_health
return @warrior.health < @last_health return health < @last_health
end end
def play_turn(warrior) def play_turn(warrior)
@warrior = warrior @warrior = warrior
if @warrior.feel.captive? if feel.captive?
@warrior.rescue! rescue!
elsif !@warrior.feel.empty? elsif !feel.empty?
@warrior.attack! attack!
elsif @warrior.health == 20 || hurt? elsif health == 20 || hurt?
@warrior.walk! walk!
else else
@warrior.rest! rest!
end end
@last_health = @warrior.health @last_health = health
end end
end end
27. Delegation Implementation
class Player
def health
@warrior.health
end
def feel
@warrior.feel
end
def rescue!
@warrior.rescue!
end
def attack!
@warrior.attack!
end
def walk!
@warrior.walk!
end
def rest!
@warrior.rest!
end
28. Delegation Implementation
class Player require 'forwardable'
def health class Player
@warrior.health
end
extend Forwardable
def feel
@warrior.feel def_delegators :@warrior, :health, :feel,
end :rescue!, :attack!, :walk!, :rest!
def rescue!
@warrior.rescue!
end
def attack!
@warrior.attack!
end
def walk!
@warrior.walk!
end
def rest!
@warrior.rest!
end
29. Domain Specific Language(DSL)
solution
DIRS.each do |dir| require 'player_helper'
if @warrior.feel(dir).ticking?
@warrior.rescue!(dir)
return class Player
end
end
include PlayerHelper
return if walk_to_ticking!
DIRS.each do |dir| def_strategries do
if should_detonate?(dir) directional(:rescue!, :ticking?)
detonate!(dir)
strategy { rest! if rest_when_ticking? }
return
end directional(:detonate!, :should_detonate?)
end directional(:attack!, :enemy?)
DIRS.each do |dir|
directional(:rescue!, :captive?)
if @warrior.feel(dir).enemy? strategy { walk!(direction_of_stairs) }
@warrior.attack!(dir) end
return
end
end
DIRS.each do |dir|
if @warrior.feel(dir).captive? Player
@warrior.rescue!(dir)
return
end
end
PlayerHelper
walk!(direction_of_stairs)
Demo!
30. DSL is Everywhere
● Rails Routing
resources :forums, :only => [:index, :show] do
resources :posts
end
namespace :admin do
resources :forums do
resources :posts, :except => [:new, :create]
end
end
31. DSL is Everywhere
● Rake Task
task :drink do
puts "I drink juice"
end
task :eat do
puts "I eat sandwich"
end
task :breakfast => [:drink, :eat] do
puts "I ate breakfast"
end
32. Conclusion:
The Ruby way I know
My RubyWarrior
Rails Rake
Script
Implementing high-
level logic is incredible
Player Rails App Rake Task simple with easy-to-
use API and DSL
Rails
Write API and create
ActiveRecord ActionMailer DSL with
PlayerHelper Rake metaprogramming
ActionPack ActiveSupport techniques
...
33. Lecture martial
● Source code is available on github
https://github.com/gaagaaga/warrior-tuesday
● i-naive
● i-oo
● i-dsl
● dsl-starter
● Slide will be on slideshare (coming soon)
34. Learning Resource
● For Beginners:
● TryRuby: http://tryruby.org/
● RubyWarrior: https://github.com/ryanb/ruby-warrior
● The Ruby Programming Language (Book)
● For Intermediate:
● Eloquent Ruby (Book)
● Metaprogramming Ruby (Book)