« first day (1648 days earlier)      last day (3576 days later) » 

 
6 hours later…
17:58
Hey @Rainbolt @murgatroid99, I have two new versions of the ManaCost/ Symbol implementation, let me know what you think! I also included a list of the benefits of each system (and links to the two branches) here: github.com/c0d3br34k3r/magic/issues/4#issuecomment-100300996
@codebreaker At a quick glance, I already prefer solution 2
Primarily because of this:
> We don't have to do two different things (other solution makes you check the Numeric and Repeatable symbols) every time we want to do a calculation, such as converted mana cost.
This is important not just for ease of use but for extensibility
@murgatroid99 yeah, I think I prefer that way too, I just wish there was a better way to make monocolor hybrid symbols
@codebreaker here's one option: make a HybridSymbol class that has 2 colors (not symbols, just colors), and a MonocolorHybridSymbol class that has 1 color, and always returns 2 for CMC
The fact is that it's extraordinarily unlikely that they will make any other kinds of hybrid symbols
@murgatroid99 It's true, I could do that, and that's sort of how I did it in my initial version, I just like the idea of having TwoPart symbols that are actually made up of two different Symbols.
@codebreaker if you don't mind, I'd like to suggest another solution on that issue (it's kind of long to write up here)
18:05
okay, sure
do you have permission to do it?
Yeah, anyone can post issues on any GitHub repo (unless it's private)
okay, that's what I thought
Actually, I'll do that a little later
I would suggest, in the second option, splitting stuff up differently
Your use of inner classes for class hierarchies is kind of weird, and Hybrid really doesn't need to be 6 layers deep in the hierarchy
I just didn't want to bloat the class with a bunch of 10-line files
besides, the actual type of mana symbols seldom matters
but I'd certainly be interested in hearing your suggestions
I would suggest the following: interface Symbol with methods converted, colors, etc
18:13
I did actually consider making Symbol an interface
Then the implementing classes would be GenericSymbol, HybridSymbol, ColoredSymbol, PhyrexianSymbol, etc.
my only issue with symbol interfaces is the creation of symbols could be public
and people could pass bogus symbols to a ManaCost builder
How would you get a bogus symbol from that hierarchy?
What is a bogus symbol?
like someone else could just implement Symbol if it was an interface
make a purple symbol or something
maybe I'm worrying too much
The way I see it, that's their problem. If it implements the interface, it should work. The fact that they're using your library in a way that you didn't intend isn't your problem
18:16
if they break the contract, yeah, I guess
Maybe they want to make their own custom Magic cards that have purple symbols
lol true
okay, well I have a partially finished interface-based Symbol implementation, maybe I'll finish that up
In any case, I would also suggest moving string parsing into its own class. Maybe SymbolFactory or something
okay, yeah, I sort of did that in Solution 1
what if they pass "{3}"
what should they get back?
So, this goes to the other suggestion that I'll write up in full on that issue
Instead of a multiset of symbols, have a ManaCostElement class that contains a Symbol and an int. Then have a ManaCostElementFactory or something
Oh, and ManaCost contains a List of those
18:19
how is that different from a multiset?
other than it's now O(n) for contains
which I suppose really isn't a big deal
It's basically the same, but it's a little more flexible, and it lets you get rid of those special ManaCost instances
You can represent an empty mana cost as an empty list, and a zero mana cost as [ManaCostElement(Generic, 0)]
@codebreaker remember, n is very small
ugh yeah I guess
I really like multisets
And I would suggest that searching for exact symbol matches is less important than costs matching a color, costs payable by a set of colors, and costs with a specific converted mana cost, all of which are O(n) anyway
@codebreaker Please understand that I'm not just trying to tear down your vision, or whatever
actually yeah, that's a good point about matching
no it's cool, different views are always good to have
Also, your NumericGroup thing seems kind of like overkill to me. As far as I can tell, you only use it once, in MonocoloredHybridSymbol, to represent the number 2
That's part of why I suggested MonocolorHybridSymbol as a separate class entirely
18:26
yeah, you're right. I thought I would use it more later. I figured maybe you could return that type from parse
For parsing, with the ManaCostElement I suggested earlier, you could basically tokenize to get each {<something>} element of the string, then pass it to ManaCostElementFactory
ManaCostElementFactory or ManaCostElementParser or whatever you call it would still need a significant switch statement, but overall I think it would be simpler
Actually, you probably wouldn't need to go that far. The ManaCostParser class could just have a function that returns a ManaCostElement for a given string
and, at that point, maybe it would be better to make parse a class method on ManaCost.
I'm mostly just thinking out loud here (so to speak)
A SymbolParser class might be useful, and mana cost parsing would basically just be doing that in a loop, so it probably wouldn't be too much more complex
Yeah, I think it would be good having the logic of what text corresponds to what symbol in its own class
I think that what I was trying to get at before with the MonocoloredHybridSymbol thing is that {2/W} can, in a sense, be defined as a symbol with color=White, CMC=2, payable with anything.
If you have it be an implementation of Symbol that defines those methods in that way, then that's all you need
Yeah, that sounds reasonable
18:45
OK, I wrote out my suggestion on that issue
okay, cool, thanks
One benefit here is that the implementation of each of the Symbol methods in each implementer is dead simple, and almost always returns either a constant or an instance variable
Oh, you're probably going to want a Symbol.devotionTo(color1, color2) because it's not exactly the same as devotionTo(color1)+devotionTo(color2)
But you can always add such stuff as you need it
for devotion, can't you just do symbol.colors().contains(color)?
if you have a cost {R/G}{R/G} it adds 2 to your "devotion to red", 2 to your "devotion to green", and 2 to your "devotion to red and green" That's what I was talking about
@codebreaker otherwise, yes, you can do that
I think, though, that it would be better to have that logic in each Symbol/ManaCostElement so that the logic in ManaCost is very simple, just add up the devotion of each element
okay, yeah, that's what I was thinking
18:55
If you do it right, just about every method on ManaCost ends up as the sum or union of that method applied to each element
The one thing that's a bit of a pain is that if you want to use ManaCostElement(Generic, 0) for {0}, you probably want to special case 0 in other ManaCostElement methods
Otherwise ManaCostElement(Color(White), 0) is a payable White mana cost with CMC 0, which is strange
I did think about that, that only generic symbols can be allowed to be 0
and then they can't have any other elements with them
I might prefer the special-case mana cost implementation for that
That's another possibility
Validate that count>=0 if Symbol is Generic, and that count>=1 otherwise
And then do a layer of validation on top of that in ManaCost
Though, maybe {0}{W} should not be an error
I think it's not really necessary to make it one
@codebreaker The other benefit of my suggestion over your second solution is increased type safety. It is impossible, with that suggestion, to create a symbol that does not appear on a real Magic card
how's that?
@murgatroid99 couldn't they pass fake symbols into either a ManaCostEntry or just a factory method for ManaCost?
19:42
@codebreaker how's what?
@codebreaker I was talking more about type safety for the purpose of your own algorithms than theoretical users

« first day (1648 days earlier)      last day (3576 days later) »