manasimu 0.0.7 → 0.0.10
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.
- checksums.yaml +4 -4
- data/ext/ford_fulkerson.so +0 -0
- data/lib/manasimu/card/pathway.rb +25 -0
- data/lib/manasimu/card.rb +67 -38
- data/lib/manasimu/data.rb +5 -1
- data/lib/manasimu/game.rb +1 -0
- data/lib/manasimu/planner.rb +68 -62
- data/lib/manasimu.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1c9780641a85a3afd2f3a9e7387681fb2c44535bed300ac32cf3d0afcc0976b
|
4
|
+
data.tar.gz: 72e18bf8bc9780cfcb765cf13dafee515354728f83c43ccc55e227b97604091f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e27d758046b0876d82ef849ceb2422ca19e92cbd4b7fc7b30b53d681f2bd1f2f556bea8f5e296500b03e04b71e621511bb3fcf0c4bf9f05b482824824a381c6c
|
7
|
+
data.tar.gz: c3b225079817f3e77c0fe1014d5077373be5265fa4f04fcec189e89b6338a4953615973657d08b928e47309bb3368e8c83e075012a3fa36d74662a01decfd9d1
|
data/ext/ford_fulkerson.so
CHANGED
Binary file
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class PathwayCard < Card
|
2
|
+
|
3
|
+
def first_produce_symbol=(symbol)
|
4
|
+
if symbol.to_i.to_s == symbol
|
5
|
+
@side = 'a'
|
6
|
+
@symbol = @card_type.color_identity[0]
|
7
|
+
else
|
8
|
+
@card_type.color_identity.each_with_index do |ci, i|
|
9
|
+
if ci == symbol
|
10
|
+
@side = @card_type.contents[i].side
|
11
|
+
@symbol = ci
|
12
|
+
break
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def color_identity
|
19
|
+
if @side
|
20
|
+
[@symbol]
|
21
|
+
else
|
22
|
+
@card_type.color_identity
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/manasimu/card.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Card
|
2
|
-
attr_accessor :id, :card_type
|
2
|
+
attr_accessor :id, :card_type, :side
|
3
3
|
|
4
4
|
def initialize(card_type)
|
5
5
|
@card_type = card_type
|
@@ -13,10 +13,12 @@ class Card
|
|
13
13
|
@card_type.drawed(turn)
|
14
14
|
end
|
15
15
|
|
16
|
-
def played(turn)
|
16
|
+
def played(turn, side = "a")
|
17
17
|
@played = turn
|
18
|
+
@side = side
|
18
19
|
@card_type.played(turn)
|
19
20
|
end
|
21
|
+
|
20
22
|
def played?
|
21
23
|
@played.nil?
|
22
24
|
end
|
@@ -29,8 +31,8 @@ class Card
|
|
29
31
|
@card_type.mana_source?
|
30
32
|
end
|
31
33
|
|
32
|
-
def playable?(lands)
|
33
|
-
@card_type.playable?(lands)
|
34
|
+
def playable?(lands, capas)
|
35
|
+
@card_type.playable?(lands, capas)
|
34
36
|
end
|
35
37
|
|
36
38
|
def types
|
@@ -61,12 +63,23 @@ class Card
|
|
61
63
|
@card_type.price
|
62
64
|
end
|
63
65
|
|
64
|
-
def
|
65
|
-
@
|
66
|
+
def reset
|
67
|
+
@side = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def max_flow(lands, capas)
|
71
|
+
@card_type.max_flow(lands, capas)
|
72
|
+
end
|
73
|
+
|
74
|
+
def edges(lands, capas)
|
75
|
+
@card_type.edges(lands, capas)
|
66
76
|
end
|
67
77
|
|
68
|
-
def
|
69
|
-
@
|
78
|
+
def mana_produced?
|
79
|
+
@side
|
80
|
+
end
|
81
|
+
|
82
|
+
def first_produce_symbol=(symbol)
|
70
83
|
end
|
71
84
|
|
72
85
|
def to_s
|
@@ -148,18 +161,42 @@ class CardType
|
|
148
161
|
end
|
149
162
|
end
|
150
163
|
|
164
|
+
def symbols
|
165
|
+
return @symbols if @symbols
|
166
|
+
@symbols = []
|
167
|
+
mana_cost[1..-2].split('}{').each_with_index do |mana, j|
|
168
|
+
spell_colors = mana.split('/')
|
169
|
+
if spell_colors.length == 1
|
170
|
+
spell_color = spell_colors[0]
|
171
|
+
if spell_color.to_i.to_s == spell_color
|
172
|
+
# numeric symbol
|
173
|
+
spell_color.to_i.times do |k|
|
174
|
+
@symbols << "1"
|
175
|
+
end
|
176
|
+
else
|
177
|
+
# color symbol
|
178
|
+
@symbols << spell_color
|
179
|
+
end
|
180
|
+
else
|
181
|
+
# multi symbol
|
182
|
+
throw Exception.new('unprogramed exception')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
@symbols
|
186
|
+
end
|
187
|
+
|
151
188
|
def price
|
152
189
|
converted_mana_cost
|
153
190
|
end
|
154
191
|
|
155
|
-
def playable?(lands)
|
156
|
-
return [false, []] if lands.empty?
|
157
|
-
return [false, []] if converted_mana_cost > lands.length
|
158
|
-
mf, used = max_flow(lands)
|
159
|
-
[mf == converted_mana_cost, used.to_a[1..lands.length]]
|
192
|
+
def playable?(lands, capas)
|
193
|
+
return [false, [], []] if lands.empty?
|
194
|
+
return [false, [], []] if converted_mana_cost > lands.length
|
195
|
+
mf, used, land_symbols = max_flow(lands, capas)
|
196
|
+
[mf == converted_mana_cost, used.to_a[1..lands.length], land_symbols]
|
160
197
|
end
|
161
198
|
|
162
|
-
def max_flow(lands)
|
199
|
+
def max_flow(lands, capas)
|
163
200
|
obj = FordFulkersonSingleton.instance.obj
|
164
201
|
# Graph has x+y+2 nodes
|
165
202
|
# source : 0
|
@@ -174,17 +211,29 @@ class CardType
|
|
174
211
|
#
|
175
212
|
|
176
213
|
# create edge
|
177
|
-
x, y, e = edges(lands)
|
214
|
+
x, y, e = edges(lands, capas)
|
178
215
|
g = Graph.new(x + y + 2)
|
179
216
|
e.each do |s, d|
|
180
217
|
g.add_edge(s, d, 1)
|
181
218
|
end
|
182
219
|
|
183
220
|
ret = obj.max_flow(g, 0, x + y + 1)
|
184
|
-
|
221
|
+
|
222
|
+
land_symbols = Array.new(lands.length)
|
223
|
+
for edges in g.G do
|
224
|
+
for edge in edges do
|
225
|
+
if edge.cap == 0 and edge.from.between?(1, x) and edge.to.between?(x+1, x+y)
|
226
|
+
land_index = edge.from - 1
|
227
|
+
spell_index = edge.to - x - 1
|
228
|
+
land_symbols[land_index] = symbols[spell_index]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
[ret, obj.used, land_symbols]
|
185
234
|
end
|
186
235
|
|
187
|
-
def edges(lands)
|
236
|
+
def edges(lands, capas)
|
188
237
|
result = []
|
189
238
|
x = lands.length
|
190
239
|
i_src = 0
|
@@ -193,29 +242,9 @@ class CardType
|
|
193
242
|
result << [i_src, i + 1]
|
194
243
|
end
|
195
244
|
|
196
|
-
# create symbol
|
197
|
-
symbols = []
|
198
|
-
mana_cost[1..-2].split('}{').each_with_index do |mana, j|
|
199
|
-
spell_colors = mana.split('/')
|
200
|
-
if spell_colors.length == 1
|
201
|
-
spell_color = spell_colors[0]
|
202
|
-
if spell_color.to_i.to_s == spell_color
|
203
|
-
# numeric symbol
|
204
|
-
spell_color.to_i.times do |k|
|
205
|
-
symbols << "1"
|
206
|
-
end
|
207
|
-
else
|
208
|
-
# color symbol
|
209
|
-
symbols << spell_color
|
210
|
-
end
|
211
|
-
else
|
212
|
-
# multi symbol
|
213
|
-
throw Exception.new('unprogramed exception')
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
245
|
# lands and mana_cost connect to each symbols
|
218
246
|
lands.each_with_index do |land, i|
|
247
|
+
next if capas[i].to_i == 0
|
219
248
|
land_colors = land.color_identity
|
220
249
|
symbols.each_with_index do |symbol, j|
|
221
250
|
if symbol == "1" or land_colors.include? symbol
|
data/lib/manasimu/data.rb
CHANGED
@@ -70,7 +70,11 @@ class Deck
|
|
70
70
|
card_type = @@card_types.find(deck_item[:set], deck_item[:setnum])
|
71
71
|
clone = CardType.create(card_type, deck_item[:name])
|
72
72
|
card_types << clone
|
73
|
-
|
73
|
+
if clone.name =~ /.*Pathway$/ and clone.mana_source?
|
74
|
+
card = PathwayCard.new(clone)
|
75
|
+
else
|
76
|
+
card = Card.new(clone)
|
77
|
+
end
|
74
78
|
deck_item[:amount].to_i.times do
|
75
79
|
card_clone = card.dup
|
76
80
|
card_clone.id = card_id
|
data/lib/manasimu/game.rb
CHANGED
data/lib/manasimu/planner.rb
CHANGED
@@ -6,6 +6,8 @@ class Planner
|
|
6
6
|
max_price = 0
|
7
7
|
max_spells = nil
|
8
8
|
max_land = nil
|
9
|
+
max_symbols = nil
|
10
|
+
max_lands = nil
|
9
11
|
|
10
12
|
if not lands_in_hand.empty?
|
11
13
|
lands_in_hand.each do |play_land|
|
@@ -18,23 +20,33 @@ class Planner
|
|
18
20
|
current_fields << play_land
|
19
21
|
|
20
22
|
# search_opt_spells
|
21
|
-
price, spells =
|
23
|
+
price, spells, symbols, lands =
|
22
24
|
search_opt_spells(current_hands, current_fields)
|
23
25
|
if price >= max_price and not spells.empty?
|
24
26
|
max_price = price
|
25
27
|
max_spells = spells
|
26
28
|
max_land = play_land
|
29
|
+
max_symbols = symbols
|
30
|
+
max_lands = lands
|
27
31
|
end
|
28
32
|
end
|
29
33
|
else
|
30
34
|
# search_opt_spells
|
31
|
-
max_price, max_spells = search_opt_spells(hands, fields)
|
35
|
+
max_price, max_spells, max_symbols, max_lands = search_opt_spells(hands, fields)
|
32
36
|
end
|
33
37
|
|
34
38
|
if not max_spells and not lands_in_hand.empty?
|
35
39
|
max_land = lands_in_hand[0]
|
36
40
|
end
|
37
41
|
|
42
|
+
if max_lands
|
43
|
+
max_lands.each_with_index do |land, i|
|
44
|
+
if not land.mana_produced?
|
45
|
+
land.first_produce_symbol = max_symbols[i]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
38
50
|
[max_land, max_spells].select {|a| a}.flatten
|
39
51
|
end
|
40
52
|
|
@@ -60,94 +72,88 @@ class Planner
|
|
60
72
|
bit_lands = 0
|
61
73
|
bit_spells = 0
|
62
74
|
# search playable spell comibantion
|
63
|
-
cost, bit_spells, bit_lands =
|
64
|
-
dfs(1, spells, lands, bit_spells, bit_lands, price)
|
65
|
-
[price, bit_select(spells, bit_spells)]
|
75
|
+
cost, bit_spells, bit_lands, land_symbols =
|
76
|
+
dfs(1, spells, lands, bit_spells, bit_lands, price, [])
|
77
|
+
[price, bit_select(spells, bit_spells), land_symbols, lands]
|
66
78
|
end
|
67
79
|
|
68
|
-
def dfs(n, spells, lands, bit_spells, bit_lands, price)
|
80
|
+
def dfs(n, spells, lands, bit_spells, bit_lands, price, total_land_symbols)
|
69
81
|
index = n - 1
|
70
82
|
|
71
83
|
# exit
|
72
|
-
return [price, bit_spells, bit_lands] if n > spells.length
|
84
|
+
return [price, bit_spells, bit_lands, total_land_symbols] if n > spells.length
|
73
85
|
|
74
86
|
spell = spells[index]
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
87
|
+
used_lands = bit_lands.to_s(2).chars
|
88
|
+
capas = lands.length.times.to_a.map do |i|
|
89
|
+
used_lands[i] == "1" ? "0" : "1"
|
90
|
+
end
|
91
|
+
|
92
|
+
# shrink
|
93
|
+
# lands_available = []
|
94
|
+
# lands.length.times do |i|
|
95
|
+
# next if used_lands[i] == "1"
|
96
|
+
# lands_available << lands[i]
|
97
|
+
# end
|
98
|
+
# capas = ("1" * lands_available.length).chars
|
79
99
|
|
80
100
|
# cast case
|
81
|
-
is_playable,
|
82
|
-
|
101
|
+
is_playable, casted_lands, land_symbols =
|
102
|
+
spell.playable?(lands, capas)
|
103
|
+
|
104
|
+
# expand
|
105
|
+
# used_lands_ = []
|
106
|
+
# land_symbols_ = []
|
107
|
+
# j = 0
|
108
|
+
# lands.length.times do |i|
|
109
|
+
# if used_lands[i] == "1" or not casted_lands
|
110
|
+
# used_lands_ << "1"
|
111
|
+
# land_symbols_ << total_land_symbols[i]
|
112
|
+
# else
|
113
|
+
# used_lands_ << casted_lands[j]
|
114
|
+
# land_symbols_ << land_symbols[j]
|
115
|
+
# j += 1
|
116
|
+
# end
|
117
|
+
# end if lands
|
118
|
+
|
119
|
+
a_price, a_bit_spells, a_bit_lands, a_land_symbols =
|
83
120
|
if is_playable
|
121
|
+
|
84
122
|
bit_spells = bit_spells | 1 << ( n - 1 )
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
123
|
+
bit_lands_ = casted_lands
|
124
|
+
.reverse
|
125
|
+
.map {|i| i.to_s}
|
126
|
+
.join('')
|
127
|
+
.to_i(2)
|
128
|
+
|
129
|
+
land_symbols_ = lands.length.times.to_a.map do |i|
|
130
|
+
land_symbols[i] ? land_symbols[i] : total_land_symbols[i]
|
131
|
+
end
|
132
|
+
|
94
133
|
# dfs
|
95
|
-
dfs(n + 1 , spells, lands, bit_spells,
|
134
|
+
dfs(n + 1 , spells, lands, bit_spells, bit_lands_,
|
135
|
+
price + spell.price, land_symbols_)
|
96
136
|
else
|
97
|
-
[nil, nil, nil]
|
137
|
+
[nil, nil, nil, nil]
|
98
138
|
end
|
99
139
|
|
100
140
|
# not cast case
|
101
|
-
b_price, b_bit_spells, b_bit_lands =
|
102
|
-
dfs(n + 1 , spells, lands, bit_spells, bit_lands, price)
|
141
|
+
b_price, b_bit_spells, b_bit_lands, b_land_symbols =
|
142
|
+
dfs(n + 1 , spells, lands, bit_spells, bit_lands, price, total_land_symbols)
|
103
143
|
|
104
144
|
if (a_price and a_price >= b_price)
|
105
|
-
[a_price, a_bit_spells, a_bit_lands]
|
145
|
+
[a_price, a_bit_spells, a_bit_lands, a_land_symbols]
|
106
146
|
else
|
107
|
-
[b_price, b_bit_spells, b_bit_lands]
|
147
|
+
[b_price, b_bit_spells, b_bit_lands, b_land_symbols]
|
108
148
|
end
|
109
149
|
end
|
110
150
|
|
111
|
-
def reverse_bit(bit, length)
|
112
|
-
s = bit.to_s(2)
|
113
|
-
length.times.to_a.map do |i|
|
114
|
-
if s[i] and s[i] == "1"
|
115
|
-
"0"
|
116
|
-
else
|
117
|
-
"1"
|
118
|
-
end
|
119
|
-
end.join.to_i(2)
|
120
|
-
end
|
121
|
-
|
122
151
|
def bit_select(cards, bit)
|
123
152
|
cards.length.times
|
124
153
|
.map { |i| cards[i] if (bit & (1 << i) > 0) }
|
125
154
|
.select { |o| o }
|
126
155
|
end
|
127
156
|
|
128
|
-
def update_bit(used_lands, bit_lands)
|
129
|
-
used_lands.each_with_index do |flg, i|
|
130
|
-
bit_lands = bit_lands | ( 1 << i ) if flg == 1
|
131
|
-
end
|
132
|
-
bit_lands
|
133
|
-
end
|
134
|
-
|
135
|
-
def fill_used_lands(used_lands, bit_lands, lands)
|
136
|
-
result = []
|
137
|
-
j = 0
|
138
|
-
lands.length.times do |i|
|
139
|
-
if (bit_lands & 1 << i) == 1
|
140
|
-
# used before dfs
|
141
|
-
result << 1
|
142
|
-
else
|
143
|
-
# used after dfs
|
144
|
-
result << used_lands[j]
|
145
|
-
j += 1
|
146
|
-
end
|
147
|
-
end
|
148
|
-
result
|
149
|
-
end
|
150
|
-
|
151
157
|
def lands(list)
|
152
158
|
list.select do |card|
|
153
159
|
card.types.include? "Land"
|
data/lib/manasimu.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manasimu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- so1itaryrove
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05-
|
11
|
+
date: 2022-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: mtg arrena mana curve simulator
|
14
14
|
email: so1itaryrove@gmail.com
|
@@ -20,6 +20,7 @@ files:
|
|
20
20
|
- ext/ford_fulkerson.so
|
21
21
|
- lib/manasimu.rb
|
22
22
|
- lib/manasimu/card.rb
|
23
|
+
- lib/manasimu/card/pathway.rb
|
23
24
|
- lib/manasimu/data.rb
|
24
25
|
- lib/manasimu/game.rb
|
25
26
|
- lib/manasimu/hello.rb
|