ascension 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.lre +1 -0
- data/.rspec +1 -0
- data/Gemfile +37 -0
- data/Gemfile.lock +128 -0
- data/Guardfile +27 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +75 -0
- data/VERSION +1 -0
- data/ascension.gemspec +129 -0
- data/lib/ascension.rb +209 -0
- data/lib/ascension/Ascension-statistics_v1.csv +49 -0
- data/lib/ascension/ability.rb +222 -0
- data/lib/ascension/card.rb +133 -0
- data/lib/ascension/cards.csv +49 -0
- data/lib/ascension/cards.rb +206 -0
- data/lib/ascension/cards2.csv +49 -0
- data/lib/ascension/events.rb +73 -0
- data/lib/ascension/parse.rb +283 -0
- data/lib/ascension/pool.rb +49 -0
- data/lib/ascension/run.rb +27 -0
- data/lib/ascension/setup_rchoice.rb +11 -0
- data/lib/ascension/to_json.rb +74 -0
- data/lib/ascension/turn_manager.rb +14 -0
- data/notes.txt +2 -0
- data/spec/card_spec.rb +87 -0
- data/spec/center_spec.rb +25 -0
- data/spec/choice_instance_spec.rb +97 -0
- data/spec/main_spec.rb +413 -0
- data/spec/parse_spec.rb +225 -0
- data/spec/spec_helper.rb +73 -0
- data/vol/dmp.json +556 -0
- data/vol/dmp2.json +1 -0
- data/vol/find_by_id.rb +22 -0
- data/vol/game.json +1 -0
- data/vol/game_pp.json +614 -0
- data/vol/test_persist.rb +44 -0
- data/web/main.rb +83 -0
- metadata +377 -0
data/lib/ascension.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'mharris_ext'
|
2
|
+
require 'rchoice'
|
3
|
+
require 'mongo_persist'
|
4
|
+
|
5
|
+
def playing_on_command_line?
|
6
|
+
$playing_on_command_line = true if $playing_on_command_line.nil?
|
7
|
+
$playing_on_command_line
|
8
|
+
end
|
9
|
+
|
10
|
+
%w(to_json).each do |f|
|
11
|
+
load File.dirname(__FILE__) + "/ascension/#{f}.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
def db
|
15
|
+
Mongo::Connection.new.db('ascension')
|
16
|
+
end
|
17
|
+
|
18
|
+
class Array
|
19
|
+
def sum
|
20
|
+
inject { |s,i| s + i }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Object
|
25
|
+
def klass
|
26
|
+
self.class
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Events
|
31
|
+
def fire(event)
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Game
|
37
|
+
setup_mongo_persist :sides, :center, :void, :honor, :deck, :turn_manager
|
38
|
+
def addl_json_attributes
|
39
|
+
%w(mongo_id engageable_cards constant_cards current_side_index last_update_dt)
|
40
|
+
end
|
41
|
+
|
42
|
+
fattr(:sides) { [] }
|
43
|
+
fattr(:center) { Center.new(:game => self) }
|
44
|
+
fattr(:void) { Void.new }
|
45
|
+
fattr(:honor) { 60 }
|
46
|
+
fattr(:deck) { CenterDeck.starting }
|
47
|
+
fattr(:center_wc) { CenterWithConstants.new(:game => self) }
|
48
|
+
fattr(:turn_manager) { TurnManager.new(:game => self) }
|
49
|
+
|
50
|
+
def engageable_cards
|
51
|
+
turn_manager.current_side.engageable_cards
|
52
|
+
end
|
53
|
+
def constant_cards
|
54
|
+
center_wc.constant_cards
|
55
|
+
end
|
56
|
+
def current_side_index
|
57
|
+
turn_manager.current_side_index
|
58
|
+
end
|
59
|
+
def last_update_dt
|
60
|
+
Time.now
|
61
|
+
end
|
62
|
+
|
63
|
+
def card_places
|
64
|
+
places = [deck,center,void]
|
65
|
+
sides.each do |side|
|
66
|
+
places += [side.hand,side.discard,side.deck,side.played]
|
67
|
+
end
|
68
|
+
places
|
69
|
+
end
|
70
|
+
|
71
|
+
def after_mongo_load
|
72
|
+
center.game = self
|
73
|
+
turn_manager.game = self
|
74
|
+
|
75
|
+
sides.each do |s|
|
76
|
+
s.game = self
|
77
|
+
%w(discard deck hand played constructs).each do |m|
|
78
|
+
s.send(m).side = s
|
79
|
+
end
|
80
|
+
s.choices.each do |c|
|
81
|
+
c.side = s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
card_places.each do |cards|
|
86
|
+
cards.hydrate!
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def find_card(card_id)
|
91
|
+
raise "blank card id" if card_id.blank?
|
92
|
+
card_places.each do |cards|
|
93
|
+
res = cards.find { |x| x.card_id.to_s == card_id.to_s }
|
94
|
+
return res if res
|
95
|
+
end
|
96
|
+
raise "no card #{card_id}"
|
97
|
+
end
|
98
|
+
|
99
|
+
class << self
|
100
|
+
def reset!
|
101
|
+
Game.collection.remove
|
102
|
+
game = Game.new
|
103
|
+
side = Side.new(:game => game)
|
104
|
+
game.sides << side
|
105
|
+
game.sides << Side.new(:game => game)
|
106
|
+
|
107
|
+
game.deck = CenterDeck.starting
|
108
|
+
#game.deck << Parse.get("Mephit")
|
109
|
+
game.center.fill!
|
110
|
+
#side.deck << game.deck.get_one('Temple Librarian')
|
111
|
+
#side.deck[-1] = Card::Hero.arha
|
112
|
+
|
113
|
+
#side.deck << Parse.get("Shade ot Black Watch")
|
114
|
+
#side.deck << Parse.get("Seer of the Forked Path")
|
115
|
+
#side.deck << Parse.get("Demon Slayer")
|
116
|
+
game.sides.each do |s|
|
117
|
+
s.draw_hand!
|
118
|
+
end
|
119
|
+
#side.hand << game.deck.get_one('Void Thirster')
|
120
|
+
#side.deck << game.deck.get_one('Void Initiate')
|
121
|
+
|
122
|
+
game.mongo.save!
|
123
|
+
game
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Side
|
129
|
+
include FromHash
|
130
|
+
setup_mongo_persist :discard, :deck, :hand, :played, :constructs, :honor, :side_id, :choices
|
131
|
+
attr_accessor :game
|
132
|
+
fattr(:discard) { Discard.new(:side => self) }
|
133
|
+
fattr(:deck) { PlayerDeck.starting(:side => self) }
|
134
|
+
fattr(:hand) { Hand.new(:side => self) }
|
135
|
+
fattr(:played) { Played.new(:side => self) }
|
136
|
+
fattr(:constructs) { Constructs.new(:side => self) }
|
137
|
+
fattr(:honor) { 0 }
|
138
|
+
fattr(:side_id) { rand(100000000000000) }
|
139
|
+
fattr(:choices) { [] }
|
140
|
+
|
141
|
+
def draw_hand!
|
142
|
+
5.times { draw_one! }
|
143
|
+
end
|
144
|
+
def draw_one!
|
145
|
+
hand << deck.draw_one
|
146
|
+
end
|
147
|
+
def play(card)
|
148
|
+
played << card
|
149
|
+
hand.remove(card)
|
150
|
+
end
|
151
|
+
def acquire_free(card)
|
152
|
+
discard << card
|
153
|
+
game.center_wc.remove(card)
|
154
|
+
fire_event Event::CardPurchased.new(:card => card)
|
155
|
+
end
|
156
|
+
def purchase(card)
|
157
|
+
acquire_free(card)
|
158
|
+
#card.apply_abilities(self)
|
159
|
+
played.pool.runes -= card.rune_cost
|
160
|
+
end
|
161
|
+
def defeat(monster)
|
162
|
+
game.void << monster
|
163
|
+
game.center.remove(monster) unless monster.name =~ /cultist/i && !game.center.include?(monster)
|
164
|
+
|
165
|
+
fire_event Event::MonsterKilled.new(:card => monster, :center => true)
|
166
|
+
|
167
|
+
monster.apply_abilities(self)
|
168
|
+
played.pool.power -= monster.power_cost
|
169
|
+
end
|
170
|
+
def engage(card)
|
171
|
+
if card.monster?
|
172
|
+
defeat(card)
|
173
|
+
else
|
174
|
+
purchase(card)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
def engageable_cards
|
178
|
+
game.center_wc.engageable_cards(self)
|
179
|
+
end
|
180
|
+
def end_turn!
|
181
|
+
played.discard!
|
182
|
+
hand.discard!
|
183
|
+
constructs.apply!
|
184
|
+
draw_hand!
|
185
|
+
|
186
|
+
end
|
187
|
+
def total_cards
|
188
|
+
[hand,played,deck,discard].map { |x| x.size }.sum
|
189
|
+
end
|
190
|
+
|
191
|
+
fattr(:events) { Event::Events.new(:side => self) }
|
192
|
+
def fire_event(event)
|
193
|
+
events << event
|
194
|
+
end
|
195
|
+
def other_side
|
196
|
+
game.sides.reject { |x| x == self }.first
|
197
|
+
end
|
198
|
+
def print_status!
|
199
|
+
puts "Center " + game.center.to_s_cards
|
200
|
+
puts "Hand " + hand.to_s_cards
|
201
|
+
puts "Played " + played.to_s_cards
|
202
|
+
puts "Constructs " + constructs.to_s_cards unless constructs.empty?
|
203
|
+
puts "Pool " + played.pool.to_s
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
%w(card cards ability pool events parse turn_manager setup_rchoice).each do |f|
|
208
|
+
load File.dirname(__FILE__) + "/ascension/#{f}.rb"
|
209
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"Realm Short","Card Type","Name","count","rune_cost","honor","runes","honor","power","+C","draw","banish_center","banish_hand","banish_discard","banish_hand_discard","discard_from_hand","special_ability","triggerable_ability","undefined"
|
2
|
+
"V","H","Void Initiate",3,1,1,1,,,"(-1)",,,,,"o1",,,,
|
3
|
+
"V","H","Spike Vixen",2,2,1,,,1,1,1,,,,,,,,
|
4
|
+
"V","H","Shade ot Black Watch",3,3,1,,,2,"(-1)",,,,,"o1",,,,
|
5
|
+
"V","C","Shadow Star",2,3,2,,,1,,,,,,,,,,
|
6
|
+
"V","H","Arbiter ot Precipice",2,4,1,,,,"2-1",2,,1,,,,,,
|
7
|
+
"V","H","Demon Slayer",2,4,2,,,3,,,,,,,,,,
|
8
|
+
"V","C","Void Thirster",2,5,3,,"1 on first_center_monster_killed","1",,,,,,,,,,
|
9
|
+
"V","H","Emeri One with the Void",1,6,3,,,4,,,,,,,,,,
|
10
|
+
"V","C","Muramasa",1,7,4,,,3,,,,,,,,,,
|
11
|
+
"E","H","Arha Initiate",3,1,1,,,,1,1,,,,,,,,
|
12
|
+
"E","H","Temple Librarian",3,2,1,,,,"(2)",2,,,,,1,,,
|
13
|
+
"E","H","Seer ot Forked Path",3,2,1,,,,1,1,"o1",,,,,,,
|
14
|
+
"E","H","Twofold Askara",1,4,2,,,,,,,,,,,"copy_hero",,
|
15
|
+
"E","H","Arha Templar",2,4,3,,,,,,,,,,,"kill_monster_4",,
|
16
|
+
"E","H","Ascetic ot Lidless Eye",2,5,2,,,,2,2,,,,,,,,
|
17
|
+
"E","C","Tablet of Times Dawn",1,5,2,,,,,,,,,,,,,
|
18
|
+
"E","C","The All Seeing Eye",1,6,2,,,,1,,,,,,,,"draw_1",
|
19
|
+
"E","H","Oziah the Peerless",1,6,3,,,,,,,,,,,"kill_monster_6",,
|
20
|
+
"E","H","Master Dhartha",1,7,3,,,,3,3,,,,,,,,
|
21
|
+
"L","H","Lifeblood Initiate",3,1,1,1,1,,,,,,,,,,,
|
22
|
+
"L","H","Wolf Shaman",3,3,1,1,,,1,1,,,,,,,,
|
23
|
+
"L","H","Runic Lycanthrope",2,3,1,2,,"2 if lifebound_hero_played",,,,,,,,,,
|
24
|
+
"L","C","Yggdrasil Staff",2,4,2,,,"1",,,,,,,,,"4_rune_to_3_honor",
|
25
|
+
"L","H","Druids ot Stone Circle",2,4,3,,,,,,,,,,,"acquire_hero_3",,
|
26
|
+
"L","C","Snapdragon",2,5,2,1,"1 on first_lifebound_hero_played",,,,,,,,,,,
|
27
|
+
"L","H","Flytrap Witch",2,5,2,,2,,1,1,,,,,,,,
|
28
|
+
"L","H","Landtalker",1,6,3,3,,,,,,,,,,,,
|
29
|
+
"L","H","Cetra Weaver ot Stars",1,7,4,,,,,,,,,,,"acquire_hero_10",,
|
30
|
+
"M","H","Mechana Initiate",3,1,1,,,,,,,,,,,"power_or_rune_1",,
|
31
|
+
"M","H","Kor the Ferromancer",1,3,2,,,2,"(1)","1 if 2_or_more_constructs",,,,,,,,
|
32
|
+
"M","C","Burrower Mk II",2,3,3,,,,"(1)","1 on mechana_construct_played",,,,,,,,
|
33
|
+
"M","H","Avatar Golem",2,4,2,,"1 foreach type_of_construct","2",,,,,,,,,,
|
34
|
+
"M","H","Reactor Monk",2,4,2,"2, 1 for construct",,,,,,,,,,,,
|
35
|
+
"M","C","Rocket Courier X-99",2,4,4,,,,,,,,,,,,,"something"
|
36
|
+
"M","C","Watchmaker Altar",2,5,5,"1 for mechana",,,,,,,,,,,,
|
37
|
+
"M","C","The Grand Deisgn",2,6,6,"2 for mechana",,,,,,,,,,,,
|
38
|
+
"M","C","Hedron Link Device",1,7,7,,,,,,,,,,,,,"all_mechana"
|
39
|
+
"M","C","Hedron Cannon",1,8,8,,,,,,,,,,,,"power_for_mechana",
|
40
|
+
"S","M","Samael's Trickster",4,"3P","-",1,1,,,,,,,,,,,
|
41
|
+
"S","M","Tormented Soul",3,"3P","-",,1,,1,,,,,,,,,
|
42
|
+
"S","M","Mephit",3,"3P","-",,2,,,,"o1",,,,,,,
|
43
|
+
"S","M","Corrosive Widow",4,"4P","-",,3,,,,,,,,,"discard_construct",,
|
44
|
+
"S","M","Mistake of Creation",4,"4P","-",,4,,"(-1)",,"o1",,"o1",,,,,
|
45
|
+
"S","M","Wind Tyrant",3,"5P","-",3,3,,,,,,,,,,,
|
46
|
+
"S","M","Sea Tyrant",3,"5P","-",,5,,,,,,,,,"discard_all_but_one_construct",,
|
47
|
+
"S","M","Earth Tyrant",2,"6P","-",,5,,2,2,,,,,,,,
|
48
|
+
"S","M","Xeron Duke of Lies",1,"6P","-",,3,,,,,,,,,"take_opponents_card",,
|
49
|
+
"S","M","Avatar ot Fallen",1,"7P","-",,4,,,,,,,,,"acquire_center",,
|
@@ -0,0 +1,222 @@
|
|
1
|
+
str = <<EOF
|
2
|
+
Card
|
3
|
+
Ability
|
4
|
+
CardChoice
|
5
|
+
RChoice
|
6
|
+
EOF
|
7
|
+
|
8
|
+
module Ability
|
9
|
+
class ChoiceInstance
|
10
|
+
include FromHash
|
11
|
+
attr_accessor :choice, :side
|
12
|
+
|
13
|
+
setup_mongo_persist :choice, :choice_id
|
14
|
+
def addl_json_attributes
|
15
|
+
%w(choosable_cards name)
|
16
|
+
end
|
17
|
+
def name
|
18
|
+
choice.class.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
fattr(:choice_id) { rand(100000000000000) }
|
22
|
+
|
23
|
+
fattr(:choosable_cards) do
|
24
|
+
res = choice.choosable_cards(side)
|
25
|
+
res = res.cards if res.respond_to?(:cards)
|
26
|
+
res
|
27
|
+
end
|
28
|
+
def save!
|
29
|
+
side.choices << self
|
30
|
+
end
|
31
|
+
|
32
|
+
def execute!(chosen_card)
|
33
|
+
choice.action(chosen_card,side)
|
34
|
+
delete!
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete!
|
38
|
+
side.choices -= [self]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class Base
|
44
|
+
fattr(:optional) { false }
|
45
|
+
include FromHash
|
46
|
+
attr_accessor :parent_card
|
47
|
+
setup_mongo_persist :parent_card
|
48
|
+
def call_until_nil(side)
|
49
|
+
loop do
|
50
|
+
choice = call(side)
|
51
|
+
yield if block_given?
|
52
|
+
return unless choice.choice.chosen_option && choosable_cards(side).size > 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
def choice_instance(side)
|
56
|
+
ChoiceInstance.new(:choice => self, :side => side)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class BaseChoice < Base
|
61
|
+
def side_for_card_choice(side)
|
62
|
+
side
|
63
|
+
end
|
64
|
+
def card_choice(side)
|
65
|
+
CardChoice.new(:ability => self, :side => side_for_card_choice(side))
|
66
|
+
end
|
67
|
+
def call(side)
|
68
|
+
card_choice(side).tap { |x| x.run! }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class CardChoice
|
73
|
+
include FromHash
|
74
|
+
attr_accessor :ability, :side
|
75
|
+
fattr(:choosable_cards) do
|
76
|
+
ability.choosable_cards(side)
|
77
|
+
end
|
78
|
+
class << self
|
79
|
+
fattr(:chooser) {}
|
80
|
+
end
|
81
|
+
fattr(:choice) do
|
82
|
+
res = RChoice::Choice.new(:optional => ability.optional, :name => ability.klass.to_s, :parent_obj => self)
|
83
|
+
choosable_cards.each do |card|
|
84
|
+
res.add_option card
|
85
|
+
end
|
86
|
+
res.action_blk = lambda { |card| ability.action(card,side) }
|
87
|
+
res.chooser = klass.chooser
|
88
|
+
res
|
89
|
+
end
|
90
|
+
def run!
|
91
|
+
choice.execute!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Banish < BaseChoice
|
96
|
+
end
|
97
|
+
|
98
|
+
class BanishCenter < Banish
|
99
|
+
def action(card,side)
|
100
|
+
side.game.center.banish(card)
|
101
|
+
end
|
102
|
+
def choosable_cards(side)
|
103
|
+
side.game.center
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class BanishHandDiscard < Banish
|
108
|
+
def action(card,side)
|
109
|
+
if side.hand.include?(card)
|
110
|
+
side.hand.banish(card)
|
111
|
+
else
|
112
|
+
side.discard.banish(card)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
def choosable_cards(side)
|
116
|
+
side.hand.cards + side.discard.cards
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class EarnHonor < Base
|
121
|
+
attr_accessor :honor
|
122
|
+
def call(side)
|
123
|
+
side.game.honor -= honor
|
124
|
+
side.honor += honor
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Draw < Base
|
129
|
+
def call(side)
|
130
|
+
side.draw_one!
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class DoCenterAction < BaseChoice
|
135
|
+
def optional; true; end
|
136
|
+
def choosable_cards(side)
|
137
|
+
side.game.center_wc.select { |x| can?(x,side) }
|
138
|
+
end
|
139
|
+
def can?(card,side)
|
140
|
+
if card.monster?
|
141
|
+
raise card.name unless card.power_cost
|
142
|
+
side.played.pool.power >= card.power_cost
|
143
|
+
else
|
144
|
+
side.played.pool.can_purchase?(card)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
def action(card,side)
|
148
|
+
if card.monster?
|
149
|
+
side.defeat(card)
|
150
|
+
else
|
151
|
+
side.purchase(card)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class KillMonster < BaseChoice
|
157
|
+
attr_accessor :max_power
|
158
|
+
def choosable_cards(side)
|
159
|
+
side.game.center_wc.select { |x| x.monster? && x.power_cost <= (max_power||99) }
|
160
|
+
end
|
161
|
+
def action(card,side)
|
162
|
+
side.defeat(card)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class AcquireHero < BaseChoice
|
167
|
+
attr_accessor :max_rune_cost
|
168
|
+
def choosable_cards(side)
|
169
|
+
#side.game.center_wc.select { |x| x.hero? }.each { |x| puts [x.name,x.rune_cost].inspect }
|
170
|
+
side.game.center_wc.select { |x| x.hero? && x.rune_cost <= (max_rune_cost||99) }
|
171
|
+
end
|
172
|
+
def action(card,side)
|
173
|
+
side.purchase(card)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class CopyHero < BaseChoice
|
178
|
+
def choosable_cards(side)
|
179
|
+
side.played
|
180
|
+
end
|
181
|
+
def action(card,side)
|
182
|
+
side.played.apply(card)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class OtherSideChoice < BaseChoice
|
187
|
+
def side_for_card_choice(side)
|
188
|
+
side.other_side
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class DiscardConstruct < OtherSideChoice
|
193
|
+
def choosable_cards(side)
|
194
|
+
side.constructs
|
195
|
+
end
|
196
|
+
def action(card,side)
|
197
|
+
side.constructs.discard(card)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class KeepOneConstruct < OtherSideChoice
|
202
|
+
def choosable_cards(side)
|
203
|
+
side.constructs
|
204
|
+
end
|
205
|
+
def action(card,side)
|
206
|
+
other = side.constructs.reject { |x| x == card }
|
207
|
+
other.each do |o|
|
208
|
+
side.constructs.discard(o)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class TakeOpponentsCard < BaseChoice
|
214
|
+
def choosable_cards(side)
|
215
|
+
side.other_side.hand
|
216
|
+
end
|
217
|
+
def action(card,side)
|
218
|
+
side.other_side.hand.remove(card)
|
219
|
+
side.hand << card
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|