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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa769c22b5954b3410dec04b773abab6ec9130953b07946ec229528cd38dd7a9
4
- data.tar.gz: 0c96dcee60c36629f885e3dbcb0c236c4a699c6bab064a323f7b56968041733f
3
+ metadata.gz: e1c9780641a85a3afd2f3a9e7387681fb2c44535bed300ac32cf3d0afcc0976b
4
+ data.tar.gz: 72e18bf8bc9780cfcb765cf13dafee515354728f83c43ccc55e227b97604091f
5
5
  SHA512:
6
- metadata.gz: 00b241f58208db388327de9e23686f41871a3f446dd99d1100589ddc777debc78c9fd551d0edc9ad220c40060fb7f1620e9986445f461a4df50b4afe32f8f171
7
- data.tar.gz: e620e1ec3ed3f2b2d5c963aa1a4fd8712c4016ca028e7e0efc13efb1abd4af1de0a88d4300145040a433656cc12e9867b5963fecf54a7008208e88c655f8a25e
6
+ metadata.gz: e27d758046b0876d82ef849ceb2422ca19e92cbd4b7fc7b30b53d681f2bd1f2f556bea8f5e296500b03e04b71e621511bb3fcf0c4bf9f05b482824824a381c6c
7
+ data.tar.gz: c3b225079817f3e77c0fe1014d5077373be5265fa4f04fcec189e89b6338a4953615973657d08b928e47309bb3368e8c83e075012a3fa36d74662a01decfd9d1
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 max_flow(lands)
65
- @card_type.max_flow(lands)
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 edges(lands)
69
- @card_type.edges(lands)
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
- [ret, obj.used]
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
- card = Card.new(clone)
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
@@ -3,6 +3,7 @@ class Game
3
3
 
4
4
  def initialize(deck)
5
5
  @deck = deck.shuffle(random: Random.new)
6
+ @deck.each { |card| card.reset }
6
7
  @hands = []
7
8
  @plays = []
8
9
  @planner = Planner.new
@@ -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
- # ex) lands [a,b,c,d]
76
- # bit_lands is 3 ( = 0011)
77
- # then left_lands to be [c, d]
78
- left_lands = bit_select(lands, reverse_bit(bit_lands, lands.length))
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, used_lands = spell.playable?(left_lands)
82
- a_price, a_bit_spells, a_bit_lands =
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
- # ex) lands [a,b,c,d]
86
- # bit_lands 3 ( = 0011)
87
- # used_lands [d]
88
- # then used_lands to be [0,0,0,d]
89
- used_lands = fill_used_lands(used_lands, bit_lands, lands)
90
- # ex) used_lands [0,0,0,d]
91
- # bit_lands 3 ( = 0011)
92
- # then bit_lands to be 11 ( = 1011)
93
- bit_lands = update_bit(used_lands, bit_lands)
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, bit_lands, price + spell.price)
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
@@ -2,6 +2,7 @@ require 'bundler'
2
2
  Bundler.require
3
3
 
4
4
  require_relative './manasimu/card.rb'
5
+ require_relative './manasimu/card/pathway.rb'
5
6
  require_relative './manasimu/planner.rb'
6
7
  require_relative './manasimu/game.rb'
7
8
  require_relative './manasimu/simulator.rb'
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.7
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-08 00:00:00.000000000 Z
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