manasimu 0.0.5 → 0.0.8

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: ca51865b8677a92f9ab33fb6897506379344a6ba0acb0e0b2958ed20cf99b47d
4
- data.tar.gz: 0f5570c68e8263f2d3e50253ecb0be090f29d5a9c648a27d5d3c74f0519ef9e0
3
+ metadata.gz: 3fcf4ab765b75c28a6f58a74bfda7d269c7e5cfc5e70428134ae1180d10808c8
4
+ data.tar.gz: 24cf80041b275bfb6319281a4690de274c53bbf84d7b346ed09db349554da192
5
5
  SHA512:
6
- metadata.gz: 9dc135c25ba5285b0b0adfba4471d80d34fc6fa626603a962b334dfbf3500a457288dcf6fefa82ddc162a4c6da773fdb2f353a264fbf20bc6cc6310805e9abb7
7
- data.tar.gz: 2003d9521abf146dbe66ebb2454b446f9627d5394562c5441bde286eb19bac0c1401f25ea5be0020832e9320bcf8933907ce110e3f1d6edd0bf1a033fa5fe12b
6
+ metadata.gz: 36302a7575cf1f9816745c859da77b2f5cf1e10b2aa8bc5491819560740a5dbde3b121379ce6d89b906637cddab44f34853d49f9128d03f67ba547370dfb0d1c
7
+ data.tar.gz: 514f55d99c0bf4a6969a1ed7b00a10e043e8c84afa7341151892d425dd2ac722547093e01feb3eacae91ebe23dc4b97521afe75d1c16e0dca9430b7f5ff9b610
Binary file
Binary file
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)
76
+ end
77
+
78
+ def mana_produced?
79
+ @side
66
80
  end
67
81
 
68
- def edges(lands)
69
- @card_type.edges(lands)
82
+ def first_produce_symbol=(symbol)
70
83
  end
71
84
 
72
85
  def to_s
@@ -75,7 +88,16 @@ class Card
75
88
  end
76
89
 
77
90
  class CardType
78
- attr_accessor :contents
91
+ attr_accessor :contents, :played, :drawed, :name
92
+
93
+ def self.create(card_type, name)
94
+ ret = card_type.dup
95
+ ret.contents = card_type.contents
96
+ ret.played = nil
97
+ ret.drawed = nil
98
+ ret.name = name
99
+ ret
100
+ end
79
101
 
80
102
  def initialize(contents)
81
103
  return if not contents
@@ -139,18 +161,42 @@ class CardType
139
161
  end
140
162
  end
141
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
+
142
188
  def price
143
189
  converted_mana_cost
144
190
  end
145
191
 
146
- def playable?(lands)
147
- return [false, []] if lands.empty?
148
- return [false, []] if converted_mana_cost > lands.length
149
- mf, used = max_flow(lands)
150
- [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]
151
197
  end
152
198
 
153
- def max_flow(lands)
199
+ def max_flow(lands, capas)
154
200
  obj = FordFulkersonSingleton.instance.obj
155
201
  # Graph has x+y+2 nodes
156
202
  # source : 0
@@ -165,17 +211,29 @@ class CardType
165
211
  #
166
212
 
167
213
  # create edge
168
- x, y, e = edges(lands)
214
+ x, y, e = edges(lands, capas)
169
215
  g = Graph.new(x + y + 2)
170
216
  e.each do |s, d|
171
217
  g.add_edge(s, d, 1)
172
218
  end
173
219
 
174
220
  ret = obj.max_flow(g, 0, x + y + 1)
175
- [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]
176
234
  end
177
235
 
178
- def edges(lands)
236
+ def edges(lands, capas)
179
237
  result = []
180
238
  x = lands.length
181
239
  i_src = 0
@@ -184,29 +242,9 @@ class CardType
184
242
  result << [i_src, i + 1]
185
243
  end
186
244
 
187
- # create symbol
188
- symbols = []
189
- mana_cost[1..-2].split('}{').each_with_index do |mana, j|
190
- spell_colors = mana.split('/')
191
- if spell_colors.length == 1
192
- spell_color = spell_colors[0]
193
- if spell_color.to_i.to_s == spell_color
194
- # numeric symbol
195
- spell_color.to_i.times do |k|
196
- symbols << "1"
197
- end
198
- else
199
- # color symbol
200
- symbols << spell_color
201
- end
202
- else
203
- # multi symbol
204
- throw Exception.new('unprogramed exception')
205
- end
206
- end
207
-
208
245
  # lands and mana_cost connect to each symbols
209
246
  lands.each_with_index do |land, i|
247
+ next if capas[i].to_i == 0
210
248
  land_colors = land.color_identity
211
249
  symbols.each_with_index do |symbol, j|
212
250
  if symbol == "1" or land_colors.include? symbol
@@ -246,22 +284,19 @@ end
246
284
 
247
285
  class CardTypeAggregate
248
286
 
249
- def find(card_type)
287
+ def find(set_code, number)
250
288
  @memo ||= []
251
- return nil if not card_type
252
- singleton = @memo.find do |c|
289
+ @memo.find do |c|
253
290
  a = c.contents[0]
254
- b = card_type.contents[0]
255
- a and b and a.name == b.name
256
- end
257
- if singleton
258
- singleton
259
- else
260
- @memo << card_type
261
- card_type
291
+ a and a.set_code == set_code and a.number == number
262
292
  end
263
293
  end
264
294
 
295
+ def add(card_type)
296
+ @memo ||= []
297
+ @memo << card_type
298
+ end
299
+
265
300
  def each
266
301
  return if not @memo
267
302
  @memo.each do |item|
@@ -293,6 +328,7 @@ class Content
293
328
  def to_s
294
329
  "[#{@name}] [#{@types}] [#{@color_identity}] [#{@mana_cost}]"
295
330
  end
331
+
296
332
  end
297
333
 
298
334
  class FordFulkersonSingleton
data/lib/manasimu/data.rb CHANGED
@@ -61,50 +61,20 @@ class Deck
61
61
  end
62
62
 
63
63
  def self.get_card_details(deck_items)
64
- path = File.expand_path( '../../../db/AllPrintings.sqlite', __FILE__ )
65
- db = SQLite3::Database.new(path)
66
- sql = <<DOC
67
- select distinct
68
- name
69
- ,number
70
- ,colorIdentity
71
- ,side
72
- ,setCode
73
- ,manaCost
74
- ,types
75
- ,text
76
- ,convertedManaCost
77
- from cards
78
- where
79
- number = ? and
80
- setCode = ?
81
- DOC
64
+ path = File.expand_path( '../../../db/card_type_aggregate', __FILE__ )
65
+ @@card_types ||= Marshal.load(File.open(path, 'r'))
82
66
  cards = []
83
67
  card_id = 0
84
- card_types = CardTypeAggregate.new
68
+ card_types = []
85
69
  deck_items.each do |deck_item|
86
- rows = db.execute(sql, deck_item[:setnum], deck_item[:set])
87
- if rows.empty?
88
- puts deck_item[:name]
70
+ card_type = @@card_types.find(deck_item[:set], deck_item[:setnum])
71
+ clone = CardType.create(card_type, deck_item[:name])
72
+ card_types << clone
73
+ if clone.name =~ /.*Pathway$/ and clone.mana_source?
74
+ card = PathwayCard.new(clone)
75
+ else
76
+ card = Card.new(clone)
89
77
  end
90
-
91
- card_type = card_types.find(
92
- CardType.new(rows.map { |row|
93
- {
94
- name: row[0],
95
- number: row[1],
96
- color_identity: row[2],
97
- side: row[3],
98
- set_code: row[4],
99
- mana_cost: row[5],
100
- types: row[6],
101
- text: row[7],
102
- converted_mana_cost: row[8]
103
- }
104
- })
105
- )
106
- card = Card.new(card_type)
107
-
108
78
  deck_item[:amount].to_i.times do
109
79
  card_clone = card.dup
110
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.5
4
+ version: 0.0.8
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-06 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
@@ -16,7 +16,7 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
- - db/AllPrintings.sqlite
19
+ - db/card_type_aggregate
20
20
  - ext/ford_fulkerson.so
21
21
  - lib/manasimu.rb
22
22
  - lib/manasimu/card.rb
@@ -45,7 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
47
  requirements: []
48
- rubygems_version: 3.1.2
48
+ rubygems_version: 3.2.3
49
49
  signing_key:
50
50
  specification_version: 4
51
51
  summary: mtg arrena mana curve simulator
Binary file