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.
@@ -0,0 +1,133 @@
1
+ module Card
2
+ module HonorEarned
3
+ attr_accessor :honor_earned
4
+ def honor_earned=(h)
5
+ @honor_earned = h
6
+ self.abilities << Ability::EarnHonor.new(:honor => h)
7
+ end
8
+ end
9
+
10
+ class << self
11
+ def dummy
12
+ Base.new(:name => "Dummy")
13
+ end
14
+ end
15
+
16
+ class Base
17
+ include FromHash
18
+ include HonorEarned
19
+
20
+ setup_mongo_persist :realm, :name, :card_id
21
+
22
+ attr_accessor :realm
23
+
24
+ # abilities are things that happen when a card is put into play or defeated
25
+ # abilities can be conditional on whether other things have already happened
26
+ fattr(:abilities) { [] }
27
+
28
+ # triggers are things than happen when external events occur.
29
+ fattr(:triggers) { [] }
30
+
31
+ fattr(:card_id) { rand(10000000000000) }
32
+
33
+ attr_accessor :name
34
+ def apply_abilities(side)
35
+ if playing_on_command_line?
36
+ abilities.each { |a| a.call(side) }
37
+ else
38
+ abilities.each do |a|
39
+ if a.respond_to?(:choice_instance)
40
+ a.choice_instance(side).save!
41
+ else
42
+ a.call(side)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ def apply_triggers(event, side)
48
+ triggers.each { |a| a.call(event, side) }
49
+ end
50
+
51
+ def monster?; kind_of?(Monster); end
52
+ def hero?; kind_of?(Hero); end
53
+ def construct?; kind_of?(Construct); end
54
+
55
+ def to_s
56
+ name
57
+ end
58
+
59
+ def basic_card?
60
+ ["Heavy Infantry","Mystic","Cultist","Apprentice","Militia","Standin"].include?(name)
61
+ end
62
+
63
+ def hydrated
64
+ return self if basic_card?
65
+ res = Parse.get(name).clone
66
+ res.card_id = card_id
67
+ res
68
+ end
69
+
70
+
71
+ end
72
+
73
+ class Purchaseable < Base
74
+ setup_mongo_persist :realm, :name, :runes, :power, :rune_cost, :card_id
75
+
76
+ fattr(:runes) { 0 }
77
+ fattr(:power) { 0 }
78
+ attr_accessor :rune_cost
79
+ def mechana?
80
+ realm == :mechana
81
+ end
82
+ end
83
+
84
+ class Hero < Purchaseable
85
+ class << self
86
+ def apprentice
87
+ new(:runes => 1, :name => "Apprentice")
88
+ end
89
+ def mystic
90
+ new(:runes => 2, :name => 'Mystic', :rune_cost => 3)
91
+ end
92
+ def militia
93
+ new(:power => 1, :name => 'Militia')
94
+ end
95
+ def heavy_infantry
96
+ new(:power => 2, :name => "Heavy Infantry", :rune_cost => 2)
97
+ end
98
+ def standin
99
+ new(:rune_cost => 2, :name => "Standin")
100
+ end
101
+ def arha
102
+ new(:rune_cost => 1, :name => "Arha Initiate").tap do |h|
103
+ h.abilities << Ability::Draw.new
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ class Construct < Purchaseable
110
+ class << self
111
+ def shadow_star
112
+ new(:power => 1)
113
+ end
114
+ end
115
+ end
116
+
117
+ class Monster < Base
118
+ attr_accessor :power_cost
119
+ setup_mongo_persist :realm, :name, :power_cost, :card_id
120
+ fattr(:runes) { 0 }
121
+ class << self
122
+ def cultist
123
+ new(:power_cost => 2, :name => "Cultist", :honor_earned => 1)
124
+ end
125
+ def cultist_standin
126
+ new(:power_cost => 2, :name => "Cultist Standin", :honor_earned => 1)
127
+ end
128
+ def cultist_standin2
129
+ new(:power_cost => 2, :name => "Cultist Standin2", :honor_earned => 1)
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,49 @@
1
+ "Realm Short","Card Type","Name","count","rune_cost","power_cost","honor","runes","honor","power","+C","draw","banish_center","banish_hand","banish_discard","banish_hand_discard","discard_from_hand","special_abilities","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 of the Precipice",2,4,,1,,,,02/01/11,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 of the 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 of the 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 Design",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,,3,,1,1,,,,,,,,,,,
41
+ "S","M","Tormented Soul",3,,3,,,1,,1,,,,,,,,,
42
+ "S","M","Mephit",3,,3,,,2,,,,"o1",,,,,,,
43
+ "S","M","Corrosive Widow",4,,4,,,3,,,,,,,,,"discard_construct",,
44
+ "S","M","Mistake of Creation",4,,4,,,4,,1,,"o1",,"o1",,,,,
45
+ "S","M","Wind Tyrant",3,,5,,3,3,,,,,,,,,,,
46
+ "S","M","Sea Tyrant",3,,5,,,5,,,,,,,,,"discard_all_but_one_construct",,
47
+ "S","M","Earth Tyrant",2,,6,,,5,,2,2,,,,,,,,
48
+ "S","M","Xeron Duke of Lies",1,,6,,,3,,,,,,,,,"take_opponents_card",,
49
+ "S","M","Avatar ot Fallen",1,,7,,,4,,,,,,,,,"acquire_center",,
@@ -0,0 +1,206 @@
1
+ class Cards
2
+ include FromHash
3
+ include Enumerable
4
+ setup_mongo_persist :cards
5
+ attr_accessor :side, :game
6
+ fattr(:game) { side.game }
7
+ fattr(:cards) { [] }
8
+ def <<(c)
9
+ cards << c
10
+ end
11
+ def remove(c)
12
+ raise "#{c} not here" unless cards.include?(c)
13
+ self.cards -= [c]
14
+ end
15
+ def each(&b)
16
+ cards.each(&b)
17
+ end
18
+ def shuffle!
19
+ self.cards = cards.sort_by { |x| rand() }
20
+ end
21
+ def empty?
22
+ size == 0
23
+ end
24
+ def size
25
+ cards.size
26
+ end
27
+ def first
28
+ cards.first
29
+ end
30
+ def pop
31
+ cards.pop
32
+ end
33
+ def index(obj)
34
+ cards.index(obj)
35
+ end
36
+ def clear!
37
+ self.cards = []
38
+ end
39
+ def include?(c)
40
+ cards.include?(c)
41
+ end
42
+ def banish(card)
43
+ remove(card)
44
+ game.void << card
45
+ end
46
+ def []=(i,card)
47
+ cards[i] = card
48
+ end
49
+ def [](i)
50
+ cards[i]
51
+ end
52
+ def to_s_cards
53
+ map { |x| x.name }.join(" | ")
54
+ end
55
+ def get_one(name)
56
+ res = find { |x| x.name == name }
57
+ raise "couldn't find #{name}" unless res
58
+ self.cards -= [res]
59
+ res
60
+ end
61
+ def hydrate!
62
+ self.cards = map { |x| x.hydrated }
63
+ end
64
+ end
65
+
66
+ class Discard < Cards; end
67
+
68
+ class PlayerDeck < Cards
69
+ def draw_one
70
+ fill_from_discard! if empty?
71
+ cards.pop
72
+ end
73
+ def fill_from_discard!
74
+ self.cards = side.discard.cards
75
+ side.discard.cards = []
76
+ shuffle!
77
+ end
78
+ def self.starting(ops={})
79
+ res = new(ops)
80
+ 8.times { res << Card::Hero.apprentice }
81
+ 2.times { res << Card::Hero.militia }
82
+ res.shuffle!
83
+ res
84
+ end
85
+ end
86
+
87
+ class Hand < Cards
88
+ def play_all!
89
+ while size > 0
90
+ side.play(first)
91
+ end
92
+ end
93
+ def discard!
94
+ each { |c| side.discard << c }
95
+ clear!
96
+ end
97
+ end
98
+
99
+ class Played < Cards
100
+ setup_mongo_persist :cards, :pool
101
+ fattr(:pool) { Pool.new }
102
+ def apply(card)
103
+ pool.runes += card.runes
104
+ pool.power += card.power
105
+ card.apply_abilities(side)
106
+ end
107
+ def <<(card)
108
+ super
109
+ apply(card)
110
+
111
+ side.fire_event(Event::CardPlayed.new(:card => card))
112
+
113
+ if card.kind_of?(Card::Construct)
114
+ remove(card)
115
+ side.constructs << card
116
+ end
117
+ end
118
+ def discard!
119
+ each { |c| side.discard << c }
120
+ clear!
121
+ self.pool!
122
+ end
123
+ end
124
+
125
+ class Void < Cards; end
126
+
127
+ module Selectable
128
+ def engageable_cards(side)
129
+ select { |x| can?(x,side) }
130
+ end
131
+ def can?(card,side)
132
+ if card.monster?
133
+ raise card.name unless card.power_cost
134
+ side.played.pool.power >= card.power_cost
135
+ else
136
+ side.played.pool.can_purchase?(card)
137
+ end
138
+ end
139
+ end
140
+
141
+ class Center < Cards
142
+ def fill!
143
+ (0...size).each do |i|
144
+ if self[i].name == 'Dummy'
145
+ self[i] = game.deck.pop
146
+ end
147
+ end
148
+
149
+ while size < 6
150
+ self << game.deck.pop
151
+ end
152
+ end
153
+ def remove(c)
154
+ raise "#{c} not here" unless include?(c)
155
+ i = index(c)
156
+ self[i] = Card.dummy
157
+ fill!
158
+ end
159
+ def banish(card)
160
+ super
161
+ fill!
162
+ end
163
+ end
164
+
165
+ class CenterWithConstants < Cards
166
+ attr_accessor :game
167
+ include FromHash
168
+ include Selectable
169
+ fattr(:constant_cards) do
170
+ [Card::Hero.mystic,Card::Hero.heavy_infantry,Card::Monster.cultist]
171
+ end
172
+ def cards
173
+ game.center.cards + constant_cards
174
+ end
175
+ def size
176
+ cards.size
177
+ end
178
+ def remove(card)
179
+ return nil if constant_cards.map { |x| x.name }.include?(card.name)
180
+ game.center.remove(card)
181
+ end
182
+ def method_missing(sym,*args,&b)
183
+ game.center.send(sym,*args,&b)
184
+ end
185
+ end
186
+
187
+ class CenterDeck < Cards
188
+ class << self
189
+ def starting
190
+ res = new
191
+ Parse::InputFile.new.cards.each { |c| res << c }
192
+ res.shuffle!
193
+ res
194
+ end
195
+ end
196
+ end
197
+
198
+ class Constructs < Cards
199
+ def apply!
200
+ each { |c| side.played.apply(c) }
201
+ end
202
+ def discard(card)
203
+ remove(card)
204
+ side.discard << card
205
+ end
206
+ 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,73 @@
1
+ events = <<EOF
2
+ hero played
3
+ construct played
4
+ monster defeated
5
+ EOF
6
+
7
+ module Event
8
+ class Events
9
+ include FromHash
10
+ attr_accessor :side
11
+ fattr(:events) { [] }
12
+ def <<(event)
13
+ event.first = true if first?(event)
14
+ self.events << event
15
+ propagate(event)
16
+ end
17
+ def propagate(event)
18
+ side.constructs.each { |c| c.apply_triggers(event,side) } if side
19
+ end
20
+ def first?(event)
21
+ events.select { |x| x.key == event.key && x.class == event.class }.empty?#.tap { |x| puts "first? #{x}" }
22
+ end
23
+ def [](i)
24
+ events[i]
25
+ end
26
+ def cond?(&b)
27
+ events.any?(&b)
28
+ end
29
+ end
30
+
31
+ class Base
32
+ include FromHash
33
+ fattr(:first) { false }
34
+ end
35
+
36
+ class CardPlayed < Base
37
+ attr_accessor :card
38
+ def realm
39
+ card.realm
40
+ end
41
+ def card_type
42
+ card.class
43
+ end
44
+ def key
45
+ [realm,card_type]
46
+ end
47
+ end
48
+
49
+ class MonsterKilled < Base
50
+ attr_accessor :card
51
+ fattr(:center) { false }
52
+ def key
53
+ [center]
54
+ end
55
+ end
56
+
57
+ class CardPurchased < Base
58
+ attr_accessor :card
59
+ def realm
60
+ card.realm
61
+ end
62
+ def card_type
63
+ card.class
64
+ end
65
+ def key
66
+ [realm,card_type]
67
+ end
68
+ end
69
+ end
70
+
71
+ class Trigger
72
+
73
+ end