Learning by doing part 2 - tc game

Hi,

I am trying to learn a bit more and I’ve decided to make my own little
trading card sort of a game.

On the link below there are two files I’ve written so far.

https://docs.google.com/folder/d/0B7TkpCLQg89MemVGblVxeVA2MDQ/edit

The problem is, that currently the summoned beast is predefined. And I
would like to make it so that user picks which one they will summon for
battle.

If I go via gets.chomp, then the result is a string and the code doesn’t
accept that.

thx
regards,
seba

Please ignore line 33 in file game.rb.

regards
seba

Hi,

You don’t create the beast anywhere. Instead, you just get the name from
the user and then call “armor” on this string – which of course doesn’t
work.

I guess you meant to write something like this:

beast_name = gets.chomp
beast = Blue_Scale_DRAGON.new beast_name

and then …beast.armor

Yes, that would be ok, but that means that the player has to create all
beasts themselves. I would like to have the beasts and later also some
spells generated randomly and have them available for player to choose
which ones they will use.

Like so:

  1. generate 10 beasts
  2. generate 10 spells

have these available in either arrays of hashes and then decide each
turn which one to use.

Something like this.

Just now I’ve tried this:

from line 33 onwards:

prompt
beast = gets.chomp

if beast == "1"
  select = derimor
elsif beast == "2"
  select = barador
end

while player_hp > 0 and ai_hp > 0
.
.
.
.


However, this gets messy if there are a lot of beasts and spells.

regards,
seba

Jan E. wrote in post #1068101:

Hi,

You don’t create the beast anywhere. Instead, you just get the name from
the user and then call “armor” on this string – which of course doesn’t
work.

I guess you meant to write something like this:

beast_name = gets.chomp
beast = Blue_Scale_DRAGON.new beast_name

and then …beast.armor

On Tue, Jul 10, 2012 at 12:39 PM, Sebastjan H. [email protected]
wrote:

have these available in either arrays of hashes and then decide each
turn which one to use.

You can do that easily:

beasts = %w{derimor barador}.map {|name| Blue_Scale_DRAGON.new name}
puts “Choose beast to summon:”
beasts.each_with_index {|b,i| puts “#{i+1}.- #{b.dragon_name}”}
beast = beasts[(gets.to_i) - 1]

Jesus.

When you’ve already got an array with the beast names, you can use the
player input as an index:

beast_names is the array with the 10 possible names

beast_name = beast_names[gets.chomp.to_i - 1]

The “- 1” is necessary if your start numbering the names with 1 instead
of 0.

Of course, you should add some kind of error handling for invalid input.

“Jesús Gabriel y Galán” [email protected] wrote in post
#1068106:

You can do that easily:

beasts = %w{derimor barador}.map {|name| Blue_Scale_DRAGON.new name}

I would create only the chosen beast and not all possible ones. This
seems more elegant to me.

“Jesús Gabriel y Galán” [email protected] wrote in post
#1068106:

On Tue, Jul 10, 2012 at 12:39 PM, Sebastjan H. [email protected]
wrote:

have these available in either arrays of hashes and then decide each
turn which one to use.

You can do that easily:

beasts = %w{derimor barador}.map {|name| Blue_Scale_DRAGON.new name}
puts “Choose beast to summon:”
beasts.each_with_index {|b,i| puts “#{i+1}.- #{b.dragon_name}”}
beast = beasts[(gets.to_i) - 1]

Jesus.

thank you both, I’ll try these suggestions and post back if I run into
problems.
Always a pleasure learning from masters:)

regards,
seba

Sebastjan H. wrote in post #1068110:

I would have the game generate a defined number of beasts and spells.
The player would then simply choose the ones for battle each turn. The
player would not generate the beasts nor spells. They would only use
them. This is the idea for now. I may change or expand later.

The player doesn’t generate anything, it’s all done by the program.

My suggestion has nothing to do with the game logic, it’s only a
technical matter: Rather than actually creating all possible beasts
(which will lead to unnecessary objects), I’d only generate the names
and later create the object for the chosen name.

Let’s say the player has to choose one beast from 1000 possible beasts.
Why would you want to create all 1000 possible beast objects and then
throw away the 999 which the player didn’t select? Wouldn’t it make more
sense to only have 1000 strings for the names and wait with the object
creation until the player has actually chosen one name?

Maybe you’re thinking too much in terms of physical objects. In order to
“generate a beast”, you don’t actually have to create a beast object.
It’s enough to have the information which identifies this beast (in this
case the name).

Jan E. wrote in post #1068109:

“Jesús Gabriel y Galán” [email protected] wrote in post
#1068106:

You can do that easily:

beasts = %w{derimor barador}.map {|name| Blue_Scale_DRAGON.new name}

I would create only the chosen beast and not all possible ones. This
seems more elegant to me.

Maybe I need to clarify a bit more.

I would have the game generate a defined number of beasts and spells.
The player would then simply choose the ones for battle each turn. The
player would not generate the beasts nor spells. They would only use
them. This is the idea for now. I may change or expand later.

I think I will expand the game in the direction that the player will
choose how many beasts and spells of each kind they want generated.

For example, I want 5 blue scale dragons, five great dire wolfs and
five earth spells. This would then be generated for the player to use.

This is just the basis for the game. The basic mechanisms.

regards,

Sebastjan H. wrote in post #1068117:

On the other hand, I am still considering this to be a small scale game
with predefined let’s say only 15 to 20 cards. However, If I were to
expand it I need this adaptation.

Well, even for 1000 objects you probably won’t notice an actual
difference in speed. But personally I find it more “clean” to only
create objects you actually need.

Jan E. wrote in post #1068114:

Sebastjan H. wrote in post #1068110:

I would have the game generate a defined number of beasts and spells.
The player would then simply choose the ones for battle each turn. The
player would not generate the beasts nor spells. They would only use
them. This is the idea for now. I may change or expand later.

The player doesn’t generate anything, it’s all done by the program.

My suggestion has nothing to do with the game logic, it’s only a
technical matter: Rather than actually creating all possible beasts
(which will lead to unnecessary objects), I’d only generate the names
and later create the object for the chosen name.

Let’s say the player has to choose one beast from 1000 possible beasts.
Why would you want to create all 1000 possible beast objects and then
throw away the 999 which the player didn’t select? Wouldn’t it make more
sense to only have 1000 strings for the names and wait with the object
creation until the player has actually chosen one name?

Maybe you’re thinking too much in terms of physical objects. In order to
“generate a beast”, you don’t actually have to create a beast object.
It’s enough to have the information which identifies this beast (in this
case the name).

You’re right, of course:) I misunderstood you earlier.
I still need to adapt the thinking process a bit and this kind of
knowledge helps a lot.

On the other hand, I am still considering this to be a small scale game
with predefined let’s say only 15 to 20 cards. However, If I were to
expand it I need this adaptation.

thx again.
regards,
seba

Jan E. wrote in post #1068119:

Sebastjan H. wrote in post #1068117:

On the other hand, I am still considering this to be a small scale game
with predefined let’s say only 15 to 20 cards. However, If I were to
expand it I need this adaptation.

Well, even for 1000 objects you probably won’t notice an actual
difference in speed. But personally I find it more “clean” to only
create objects you actually need.

One more thing, are we talking about the same “selection”? I was
referring to selection of one of the beasts from the deck for each turn
of the battle.

And I think you’re referring to the deck selection.

Obviously the game needs both, they’re just different steps.
And for the deck selection I only wanted the player input on the card
types (beasts, spells,…). One may want to play only with let’s say
beasts while others prefer spells. And that’s the deck selection. Once
the deck is determined, players select cards for each turn.

regards,
seba

On Tue, Jul 10, 2012 at 3:18 PM, Sebastjan H. [email protected]
wrote:

One more thing, are we talking about the same “selection”? I was
referring to selection of one of the beasts from the deck for each turn
of the battle.

And I think you’re referring to the deck selection.

Obviously the game needs both, they’re just different steps.
And for the deck selection I only wanted the player input on the card
types (beasts, spells,…). One may want to play only with let’s say
beasts while others prefer spells. And that’s the deck selection. Once
the deck is determined, players select cards for each turn.

What Jan is saying is that you should defer the creation of the actual
Ruby object until the last time, to avoid creating objects that are
not going to be used.
In my opinion, the last responsible time is the one where you need
some value from the object. So if you need to actually create the
objects or not for the deck selection depends on if the “key” (the
name) is enough for the user to choose or not. For example:

cards = %w{derimor barador fireball invisibility} # all the “keys” of
the possible cards
deck_card_names = []
while deck_card_names.size < 15 # or 20
puts “Choose cards for deck”
cards.each_with_index {|c,i| “#{i+1}.- #{c}”}
card = cards[gets.to_i - 1]
print "quantity: "
qty = gets.to_i
qty.times {deck_card_names << card}
end

while true
puts “Choose card to play”
deck_cards_name.each_with_index {|c,i| “#{i+1}.- #{c}”}
card = Blue_Scale_DRAGON.new deck_cards_name[gets.to_i - 1]
end

Of course if you need the info of the card at choosing time, you might
need to instantiate the cards when choosing, for example if you need
to know the type or whatever. Depending on how you plan to generate
and use the cards, there might be better choices than an array. If you
might have a number of identical cards, maybe a hash of “name” => qty
or even “name” => {“qty”: 4, “type”:spell} or more complex stuff might
be more appropriate.

Jesus.

From: Sebastjan H. [email protected]

One side note, why this: puts "#{beast} strikes with: " produces
this:
#<Blue_Scale_DRAGON:0x8a225d0> strikes with:?

When I’ve seen similar things in my code, I resort to using
"#{beast}.to_s to
coearse the variable into a string. I’m sure one of the more
knowledgeable folks
will explain the why (because I have always thought that’s what
#{variable} did
without using the .to_s).

Wayne

Thank you for the clarification. I understand the difference and I have
to first fully determine the logic and the mechanics I want and then
adjust the code.

One side note, why this: puts "#{beast} strikes with: " produces this:
#<Blue_Scale_DRAGON:0x8a225d0> strikes with:?

I am guessing it has to with the class, but would I get the actual name
of the beast which dealt the damage?

regards
seba

Wayne B. wrote in post #1068186:

From: Sebastjan H. [email protected]

One side note, why this: puts "#{beast} strikes with: " produces
this:
#<Blue_Scale_DRAGON:0x8a225d0> strikes with:?

When I’ve seen similar things in my code, I resort to using
"#{beast}.to_s to
coearse the variable into a string. I’m sure one of the more
knowledgeable folks
will explain the why (because I have always thought that’s what
#{variable} did
without using the .to_s).

Wayne

Hi,

I’ve tried it and I got #<Blue_Scale_DRAGON:0x90653ac>.to_s

I’ve tried other variations with .to_s and still doesn’t work.

regards
seba

Sebastjan H. wrote in post #1068181:

One side note, why this: puts "#{beast} strikes with: " produces this:
#<Blue_Scale_DRAGON:0x8a225d0> strikes with:?

I am guessing it has to with the class, but would I get the actual name
of the beast which dealt the damage?

How is the object supposed to know that you want the value of @name when
you transform it into a string? You have to define a custom “to_s”
method. If you don’t, the object will use the one provided by the Object
class (which returns this identifier string).

But in this case it makes more sense to simply get the name:

"#{beast.dragon_name} strikes with: "

Jan E. wrote in post #1068190:

Sebastjan H. wrote in post #1068181:

One side note, why this: puts "#{beast} strikes with: " produces this:
#<Blue_Scale_DRAGON:0x8a225d0> strikes with:?

I am guessing it has to with the class, but would I get the actual name
of the beast which dealt the damage?

How is the object supposed to know that you want the value of @name when
you transform it into a string? You have to define a custom “to_s”
method. If you don’t, the object will use the one provided by the Object
class (which returns this identifier string).

But in this case it makes more sense to simply get the name:

"#{beast.dragon_name} strikes with: "

Jan thank you again. I should have seen this. I think I best turn in:)

regards,
seba

I’ve done quite some reprogramming according to the advises above and I
need help yet again.

  1. I haven’t uploaded the new files yet as google docs isn’t really the
    best solution for this. Which brings me to a sub-question: What
    repository is best (I mean most user friendly for a beginner). I am
    using Bazaar offline and I’ve had some difficulties using the Launchpad.

  2. Launchpad requires me to state the license. If I have a project like
    this (consisting of several files), where do I state the license and is
    this entirely up to me as the author?

  3. And for the big one:

I am using a hash with beast names and types:

possible_cards = {“derimor” => “dragon”, “barador” => “dragon”,
“teragon” => “dragon”, “gali” => “dragon”, etc…


I also get the user input for the number of each type:


Select the number of dragons

def select_number_of_dragons()
puts “Select the number of dragons (max. 5)”
@dragons_qty = gets.chomp.to_i
if @dragons_qty < 1 or @dragons_qty > 5
puts “The number of dragons is invalid. Enter a number between 1 and
5.”
return select_number_of_dragons()
end
return @dragons_qty
end

Now I would like to have as many beasts/spells from the hash generated
as user specified. If dragon_qty is 4 then the first (or maybe also
random) 4 dragons from the hash are to be generated.

I’ve tried the iterating with loop “for i in 0…dragon_qty” but that
actually multiplies each dragon by dragon_qty:(

thank you.

kind regards,
seba