From: "Jesús Gabriel y Galán" Date: 2012-07-18T21:20:24+09:00 Subject: Re: learning by doing part 2 - tc game On Wed, Jul 18, 2012 at 2:02 PM, Sebastjan H. wrote: > I need (hopefully) one final help for this game:) > > I am trying to program the battle turn and I just wanted to know whether > there is any better or more elegant solution other than branching so > much: > > ------------------------------------------------------------- > ## Here it needs to branch according to card attributes: spells don't > have attacks. > if card.type == "armor_spell" > player_hp = player_hp + card.armor > > elsif card.type == "healing_spell" > player_hp = player_hp + card.heal > > elsif card.type == "debuff_spell" > if ai_card.type == "dragon" or ai_card.type == "dire wolf" > ai_card.attack = ai_card.attack - card.debuff > end > > elsif card.type == "dragon" or card.type == "dire wolf" > if ai_card.type == "dragon" or ai_card.type == "dire wolf" > player_hp = player_hp + card.armor - ai_card.attack > puts "#{ai_card.name} strikes with " + ai_card.attack.to_s > puts "\n" > > end > > if ai_card.type == "armor_spell" > ai_hp = ai_hp + ai_card.armor > > elsif ai_card.type == "healing_spell" > ai_hp = ai_hp + ai_card.heal > > elsif ai_card.type == "debuff_spell" > if card.type == "dragon" or card.type == "dire wolf" > card.attack = card.attack - ai_card.debuff > end > > elsif ai_card.type == "dragon" or ai_card.type == "dire wolf" > ai_hp = ai_hp + ai_card.armor - card.attack > puts "#{card.name} strikes with: " + card.attack.to_s > end > > > @deck.delete(card) > @ai_deck.delete(ai_card) > puts "Player health is #{player_hp}." > puts "Ai health is #{ai_hp}." > ------------------------------------------------------------- > thank you very much. One approach that implies a huge refactor of your datastructures, would be to have each card object implement its own logic on the game state: class ArmorCard attr_reader :armor_level def initialize armor @armor_level = armor end def perform_action game_state game_state.increment_player_hp(armor) end end class HealingSpellCard attr_reader :spell_level def initialize spell_level @spell_level = spell_level end def perform_action game_state game_state.increment_player_hp(spell_level * 2) #healing spells heal double their level (example of spell logic) end end Then you only need to call the perform_action method in each card object. If you have common logic, such as attack card only differing in name and attack value, but the attack logic is the same, then you could model it with a class hierarchy: class Card def is_attack? false end end class AttackCard < Card def is_attack? true end def perform_action game_state game_state.increment_player_hp(armor) if game_state.ai_card.is_attack? game_state.increment_player_hp(-ai_card.attack) end end end class Dragon < AttackCard attr_reader :armor, :attack def initialize armor, attack @armor = armor @attack = attack end end And so on. You might have different classes depending on characteristics or other ways to model it: maybe AttackCard, SpellCard, etc could be modules you mixin in specific cards, for example if some card can be both. Then maybe you could have a general implementation of perform_action in the Card class. It depends. I hope this gives you some ideas. Jesus.