Skip to content

Instantly share code, notes, and snippets.

@alxjrvs
Created December 18, 2013 02:39
Show Gist options
  • Save alxjrvs/8016472 to your computer and use it in GitHub Desktop.
Save alxjrvs/8016472 to your computer and use it in GitHub Desktop.
Stutorial
Imagine breaking down the Rules text on “Lightning bolt”, written backwards with regards to structural rules.
So, we might start at the most universal aspect of a magic card - it is a “Card”, in a game that cares about cards.
How do we go deeper? we can divide at permanents and non permanents. One kind of spell creates a permanent, the other does not. So lets go on to “Non Permanents”, then.
From here, we break into more recognizable game attributes - Instants and Sorceries, each with their own rules.
What we have is a class hierarchy, each a level of rules that apply at that level and also every level moving forward. What matters to a “Card” matters to a “Sorcery”, because “Sorcery” is a kind of “NonPermanent”, which itself is a “Card”.
Sorcery < NonPermanent < Card.
What are the rules that apply to a card?
They have:
- A Name
- Mana Costs
- Supertypes, Types, Subtypes
- Rules
(and, in more superfluous terms, artist, rarity, expansion, etc).
What about the next level of the chain - NonPermanents.
In this case, NonPermanents don’t have much more than Cards. If we were discussing permanents, we could add Power and Toughness, something that NonPermanents don’t have.
NonPermanents do have a rules clause: “Goes to the graveyard immediately upon resolution”. So we add that.
And in the final level, “Instant”, the rule is simple but powerful: “Can be played whenever the stack is empty and you have priority”.
So we have a Class Hierarchy of rules, and what applies at the highest level is relevant to the lowest, but the lower rules are not relevant to their ‘parent’.
This is no so different than how classes work in ruby.
Classes are collections of rules, and they apply internally for objects. You can create “Children” of these classes, which inherit their rules, but can create new rules of their own.
Imagine this a class with some code designed to say “hello” to the user. So, it says:
class Greeting
def speak
puts “Hello World!"
end
end
This contains some stuff that you don't recognize, but some of it might be understandable.
"class Greeting" - this tells us that there is a new class, named "Greeting", and the rest of the code on the page belongs to that class - at least, all the code that comes before the matching "end". Ruby doesn't require that you indent your code, but it makes it much more readable. (note: Case is important in ruby. almost everything is lower-case, except for Constants (WRITTEN IN CAPS) and class names (Written In Snake Case). More on Constants later.)
The stuff inside is new. "def" defines a method, which is a small amount of executable code local the the class it is being called from. A method is like a magic "rule" - they are local to the class where they are created and any descendents of that class down the hierarchy, but not up it.
This one contains a method named "#speak", which executes the code inside of it. (Note: it is common ruby notation to refer to methods with a hash sign in front of it. "#speak", for instance. )
"#puts" is another method, one from up in the chain from this. It is a core internal ruby method, and is available everywhere. It prints the following string (a collection of characters) to the console. So this method prints "Hello world" to the browser.
This is an instance method, which means that it runs from instances of that class. Classes can have methods that run on themselves, but they aren't as interesting.
Instances are little alive bits of code that can contain and hold variables and run methods on them. For now, we're keeping it simple - this contains one little method that executes code that prints "Hello World" to the console.
So lets get it to talk. In the ruby interpreter:
>> greeter = Greeter.new
This calls the class method "#new" (which, like "#puts", is another deep-ruby thing), which creates a new instance of the "Greeter" class. we also save it to the variable "greeter", so we can access it later. We could have named it anything we want, but we want to understand it later.
Now, lets call our "#speak" method on it.
>> greeter.speak
and the promt returns...
=> "Hello world!"
Who'd a thunk.
CONSIDER THE FOLLOWING, AND WHAT IT MEANS:
class MeanGreeter < Greeter
def mean_speak
speak
puts "Get The Fuck out!"
end
end
class NiceGreeter < Greeter
def happy_speak
speak
pugs "Welcome, friend!"
end
end
AND WHAT WOULD HAPPEN IF I DID THIS
>> nice = NiceGreeter.new
>> nice.happy_speak
>> nice.speak
>> mean = Meangreeter.new
>> mean.mean_speak
>> mean.speak
And for extra credit, what would happen if I did this?
>> mean.happy_speak
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment