
RubyWarrior - Bloc - Dekku
https://www.bloc.io/ruby-warrior/
======
phoboslab
Very cool! Proud to see that it's made with ImpactJS[1] (my game engine :))

[1] [http://impactjs.com/](http://impactjs.com/)

~~~
nathas
Hey! You made ImpactJS? That's very cool, but it's really hard to commit $99
to buy an engine when I can't even try it! It looks super-rad and I'd love to
give it a shot, but it's a bit high of a bar for a casual game dev.

~~~
phoboslab
If you buy it and don't like it for whatever reason, I can give you a full
refund within the first month. That's easier for me to handle than a separate
trial license.

~~~
hayksaakian
I never thought about it that way.

Totally stealing that idea.

~~~
nathas
Just anecdotal, but we tried that for a while. Our signups and conversions are
much higher with a trial. I work on a SaaS product.

------
teh_klev
Great...but how about turning down the music volume. It's 2:20am here, I
opened the page and had a trouser changing moment and woke up the neighbours.

------
twelvechairs
Nicely made. Some frustrations:

\- while, until, retry (and others?) not allowed.

\- not being able to see the class of something. Its more ruby style to do
'space.is_a?(Enemy)' than 'space.enemy?'. This would also help to build case
statements rather than lots of ifs.

\- no 'print' or 'puts'. How am I supposed to know what 'look' returns when it
never really tells me?

\- I prefer a single set of rules rather than adding rules as you go. When
first I have to use :backward but later this becomes basically redundant as
'pivot' is added, it just makes me frustrated in having to refactor. Same
thing for feel/look.

~~~
examancer
I don't feel `.is_a?(Class)` is ever idiomatic ruby. You should always be
coding to an interface, not an implementation. This prevents things like mocks
and duck typing, making testing more difficult and adding complexity when you
want to add AnotherEnemy that doesn't share the same inheritance tree.

I try to avoid using `.is_a?(Class)` in all of my ruby code when possible.
`.respond_to?` is much more responsible way of probing whether an object has
the interface you are looking for.

~~~
dragonwriter
> I try to avoid using `.is_a?(Class)` in all of my ruby code when possible.
> `.respond_to?` is much more responsible way of probing whether an object has
> the interface you are looking for.

#is_a?(class) is a much more specific check of semantics than
#respond_to?(method_name). is_a? is the more cautious approach (least likely
to produce false positives at the expense of being most likely to produce
false negatives) whereas respond_to? is the less cautious approach (least
likely to produce false negatives while most likely to produce false
positives.)

~~~
mceachen
Are you coming from java? That's my background (at least one of them), and
felt that way too. Interface === API contract == safe.

But that really isn't the only way to do things. Read up on
[http://en.wikipedia.org/wiki/Duck_typing](http://en.wikipedia.org/wiki/Duck_typing)

~~~
dragonwriter
> Are you coming from java?

Well, java was one of the languages I used before Ruby, but I've done more
Ruby than Java.

> Read up on
> [http://en.wikipedia.org/wiki/Duck_typing](http://en.wikipedia.org/wiki/Duck_typing)

I am well aware of duck typing, and rarely use either #is_a? or #respond_to?

That doesn't change that, _if_ you have a reason to use that type of inquiry
to check interfaces, #is_a? is the more safe of the two (more likely to reject
an object that provides the semantics of concern and less likely to accept one
that does not) and #respond_to? is the less safe (more likely to accept an
object that does not provide the semantics of concern and less likely to
reject one that does.)

------
epidemian
This should win every level (given enough tries):

    
    
      def play_turn(warrior)
        m = warrior.methods.grep(/.!$/).sample
        warrior.send(m, *([nil, :backward].sample if m != :rest!))
      end
    

(that sucker of :rest! that doesn't accept a direction argument!)

It's kind of amusing to see the warrior do random stuff like shooting arrows
backwards and pivoting back in the worst possible moments. Too bad that Run
button repeats the same movements if you didn't edit the source code somehow.

Great game and concept BTW!

~~~
aperley
The sandbox probably always initializes with the same random seed.

~~~
epidemian
No, it seems to be a client-side thing. If no edit was made in the code editor
since last run it doesn't make the request to
[https://www.bloc.io/api/v1/ruby_warrior_players/:id](https://www.bloc.io/api/v1/ruby_warrior_players/:id)
(which seems to be the one that returns the warrior and enemy movements).
Repeating the same request in cURL multiple times does return different
results.

------
hcarvalhoalves
Had a lot of fun with my rusty Ruby on this game. Here's my solution to beat
level 3 onwards:

[https://gist.github.com/hcarvalhoalves/6096888](https://gist.github.com/hcarvalhoalves/6096888)

------
hayksaakian
It would be cool if the game commited your code to a github repo every level.

This way you could see your own progress, and see what solutions other came up
with without bugging them.

~~~
rpicard
Maybe a gist would be appropriate?

------
saebekassebil
Had to implement a

    
    
        if not warrior
          return nil
        end
    

in the play_turn method, to workaround a bug. But other than that, this is
great!

------
joshuak
Akkk... sound... must... turn... off!!!

Ok default sound way too loud, and at least on Safari the little speaker icon
in the top left doesn't seem to do anything.

------
jtms
I am really disappointed that Ryan Bates is not being STRONGLY credited
anywhere on this page... this is just a graphical wrapper on his original
creation.

[https://github.com/ryanb/ruby-warrior](https://github.com/ryanb/ruby-warrior)

~~~
endlessvoid94
It's in the footer...

~~~
jtms
ah so it is... was below the fold and I didn't see it :-/

------
stormbrew
Feature request: After you've beaten it once let you go through all levels
with the same code. Right now it doesn't let you use the features it hasn't
told you about.

------
jimparkins
As someone who has never done any development in Ruby. I loved the idea and
wanted to use. However what makes it not accessible is that you give no
instruction initially on the structure of Ruby syntax. This means that I would
need to follow another book or tutorial. Please consider drip feeding the
player a syntax cheat sheet that will help with each level .

------
marcamillion
This is VERY, VERY awesome.

As a web-rubyist, this forces me to think in a different way than I normally
would.

Thank you for making this.

------
StavrosK
Oh goddamn, this is amazing. As someone who hasn't even seen Ruby code before,
you could include a bit more on the syntax of conditional/loop constructs
(if/while/etc), but it's amazing. I'll send this to my non-programmer friends
right now.

------
lostdog
It would be great if either `print` or `puts` worked.

~~~
stormbrew
I have to admit I kind of like that it doesn't. All games have artificial
constraints and I feel like keeping you from inspecting too much of the
internal state is a reasonable one for this.

~~~
roryokane
I would like it to debug my own code. You are more aware of the artificial
nature of the variables you create, so it’s not as world-breaking to inspect
their contents.

I saved a `health_change` variable in my code, and decided what to do based on
that, but the warrior did the wrong thing. I wanted to see if my variable was
being set correctly by printing it each turn, but I couldn’t. My normal tool
for understanding what was going on is missing, so I was forced to guess at
the bug. I finally got it to work by reversing the order of two terms in my
formula for `health_change`, but it was a lot harder to understand what was
going on when I could only guess at or simulate the values of the variables.

------
matthuggins
Cool idea, but I don't think it makes sense for there to be both a Player
class and a warrior object. They seem like they are/should be one in the same.
At the very least, I think behind the scenes, the Player class should look
more like this such that the warrior object is always available, and I don't
need to pass it around from method to method that I define. e.g.:

    
    
        class Player
          attr_reader :warrior
    
          def initialize(warrior)
            @warrior = warrior
          end
    
          def play_turn
            # I can now access `warrior` here or in any other methods I write
          end
        end

~~~
snikch
The player object would represent the current person playing the game, i.e.
you. The warrior represents the object on the screen. The player tells the
warrior to take actions, so it makes sense that they're different objects.

If there were multiple warriors then your code would no longer make sense, as
the control logic would have to be changing the player_instance.warrior
object.

~~~
xentronium
> If there were multiple warriors then your code would no longer make sense,
> as the control logic would have to be changing the player_instance.warrior
> object.

You need to keep previous state about warrior. E.g. delta health.

------
joemclarke
This is awesome, glad to see I can put my ruby skills to good use playing a
game!

------
mmanfrin
This is really great, but it would be even better if it showed where the error
it's finding is located. I am getting some weird errors that I can't spot-
find.

~~~
jtms
just play the original: you can use a the text editor of your choice, run in
terminal, run with or without animation (nearly instant), and you have full
debugging capabilities via puts. Also you get the rogue-like ascii graphics
which is the original inspiration for the game.

------
DanielRibeiro
Discussion from yesterday:
[https://news.ycombinator.com/item?id=6110382](https://news.ycombinator.com/item?id=6110382)

------
Stratego
I really like how this manages to introduce some object-oriented principles
stealthily while mostly focusing on linear logic. Great job!

------
hardwaresofton
First couple seconds was wondering where the hell the sound was coming from,
rest of the seconds were in awe. Awesome job.

------
nonrecursive
Oh man, I love this!

I especially loved this: "warrior.feel.empty?". Allova sudden my RubyWarrior's
getting all existential!

------
ulisesrmzroche
How do you tell the character to stop on a space when walking? That monster
keeps killing me.

~~~
Hovertruck

        if warrior.feel.enemy?
          warrior.attack!
        else
          warrior.walk!
        end

------
hayksaakian
They should also add the intermediate levels as well

[https://github.com/ryanb/ruby-
warrior/tree/master/towers/int...](https://github.com/ryanb/ruby-
warrior/tree/master/towers/intermediate)

------
chrischen
You should do a score based on the number of lines of code or characters you
have to use.

------
soheil
kneel down before the warrior (all levels):
[https://gist.github.com/syasrebi/6097679](https://gist.github.com/syasrebi/6097679)

~~~
patrickdavey
I aint kneeling before any warrior that shoots captives (level 8!)

------
Lord_DeathMatch
"undefined method `elements' for [:return0]:Array"

Marvelous

~~~
jasonm23
don't use `return` in your functions.

------
lcedp
Does anyone know more games like this? Thanks.

------
gpxl
This is a lot of fun. Well done! :)

------
Bluestrike2
Ok, that's kind of fun :).

------
lcedp
I made it. It was great!

------
innguest
This is very cool. I hope others copy your idea - very nice way to marry
programming with games.

