Friday, September 29, 2006
Vi for Mac OS X eveverywhere!
Tuesday, June 27, 2006
Thursday, June 01, 2006
Two Friends at a Cafe
The following takes place at an outdoor table of the Jester's
Cafe in Kingstown, Mittelland. Sitting at this table is Mr. Arthur
Shortbush, a Kingstown business-man. He is taking his morning coffee
(where the morning is eleven A.M.), and reading the Kingstown
Informer, a paper chiefly for the entertainment of business-men.
We observe Mr. Shortbush for a while, he is like his namesake
short, barely four foot eleven inches. He does however have the
advantage of the most wonderful thick, and perfectly neat brown hair.
Many would say it was his most attractive feature. Mr. Shortbush is
not lazy to be up so late, but the Markets are closed today, and he
relaxes for the moment, sure that his investments are secure.
By-and-by we see Mr. Shortbush's good friend come up the
street and join Shortbush at the table.
"You still read that rag?" Mr. Shortbush's friend is of course
referring to the already mentioned Kingstown Informer. Mr. Shortbush
folds up the paper in response.
"I must keep up with my business affairs."
"Don't lie, I know you read that thing for fun." Lord
Southwell is of course completely correct. Lord Southwell being Mr.
Shortbush's friend. Lord Southwell is actually a relatively minor
personage, which no land worth speaking of. He is unfortunately tall,
undesirably lanky and not very handsome. His only saving grace as far
as the general populace was concerned was that that he had the
friendship and esteem of (the very rich) Mr. Shortbush.
"I would never lie to you Leon." We wonder whether Mr.
Shortbush is being genuine. "However, there was a rather interesting
article in today's 'rag'. It seems Southland man has received
permission and financing from the Westland monarchy to try a mad
expedition to the other side of the world."
"Ah yes. DeMerro is his name right? I wonder what he plans to
do when he gets to the other side of the world."
"Well considering the Southlander nature, I imagine he intends
to throw a ball." Lord Southwell laughs uproariously at Mr.
Shortbush's witticism. The other diners and people in the vicinity do
not think it nearly as clever.
Mr. Shortbush continues, "Yes, it says here he will have a
fleet of five ships. Is five really a fleet I wonder? My own merchant
fleet exceeds fifteen, although my ships don't appear to be nearly as
large as this madman's. Five ships will depart from southernmost port
in Westland, and travel west, all around the earth until they arrive
in the Distant East. It goes on and on about the minutiae of sailing,
not very interesting I should think.
"Fancy a card game?"
"I suppose I could do with a hand or two." replies Lord
Southwell.
Tuesday, May 02, 2006
Animal Crossing: WW
Saturday, April 15, 2006
Packrat parsers
% cat parser.rb
module Parser
NoMatch = Object.new
BadMatch = Object.new
def Lit(*args)
Parser::Lit(*args)
end
def self.Lit(val)
LiteralMatcher.new(val)
end
def self.included(mod)
s = self
(class << mod; self; end).module_eval do
define_method(:Lit) do |*args|
s.Lit(*args)
end
end
end
mod = self
(class << BadMatch; self; end).class_eval do
define_method(:to_s) { "#{mod}::BadMatch" }
end
(class << NoMatch; self; end).class_eval do
define_method(:to_s) { "#{mod}::NoMatch" }
end
module ParserHandlers
attr_accessor :parse_succeeded_proc, :parse_failed_proc
def on_parse(&block)
self.parse_succeeded_proc = block
end
def on_error(&block)
self.parse_failed_proc = block
end
def |(other_parser)
Or.new(self, other_parser)
end
def>>(other_parser)
Sequence.new(self, other_parser)
end
def _?
ZeroOrOne.new(self)
end
private
def post_parse(parse_results, current_token)
case parse_reslts
when NoMatch, BadMatch
return parse_failed_proc.call(current_token) if parse_failed_proc
parse_results
else
return parse_succeeded_proc.call(parse_results) if parse_succeeded_proc
parse_results
end
end
end
class EndOfStream
include ParserHandlers
def initialize()
end
def parse(token_stream)
if token_stream.end_of_stream? or token_stream.current == EOS
post_parse(true, nil)
else
post_parse(NoMatch, token_stream.current)
end
end
end
class LiteralMatcher
include ParserHandlers
def initialize(const)
@const = const
end
def parse(token_stream)
token = token_stream.current
if @const === token
token_stream.advance
post_parse(token, token)
else
post_parse(NoMatch, token)
end
end
end
class Or
include ParserHandlers
def initialize(first_choice, second_choice, *remaining_choices)
@parser_choices = [first_choice, second_choice, *remaining_choices]
end
def parse(token_stream)
result = NoMatch
@parser_choices.each do |parser|
choice_result = parser.parse(token_stream)
if choice_result == BadMatch or choice_result != NoMatch
result = choice_result
break
end
end
post_parse(result, token_stream.current)
end
def []=(index, value)
@parser_choices[index] = value
end
def |(additional_choice)
@parser_choices << additional_choice
self
end
end
class Sequence
include ParserHandlers
def initialize(parser_first, parser_second, *rest)
@parsers = [parser_first, parser_second, *rest]
end
def parse(token_stream)
first_parser, *remaining_parsers = @parsers
results = []
first_result = first_parser.parse(token_stream)
if first_result != NoMatch
results << first_result
else
return post_parse(NoMatch, token_stream.current)
end
remaining_parsers.each do |parser|
result = parser.parse(token_stream)
if result == NoMatch or result == BadMatch
return post_parse(BadMatch, token_stream.current)
end
results << result
end
post_parse(results, token_stream.current)
end
def []=(index, value)
@parsers[index] = value
end
def>>(other_parser)
@parsers << other_parser
self
end
end
class ZeroOrOne
include ParserHandlers
def initialize(parser)
@parser = parser
end
def parse(token_stream)
result = @parser.parse(token_stream)
if result == NoMatch
post_parse(true, token_stream.current)
else
post_parse(result, token_stream.current)
end
end
end
class ZeroOrMany
include ParserHandlers
def initialize(parser)
@parser = parser
end
def parse(token_stream)
results = []
loop do
result = @parser.parse(token_stream)
return post_parse(BadMatch, token_stream.current) if result == BadMatch
break if result == NoMatch
results << result
end
post_parse(results, nil)
end
end
class ArrayTokenStream
attr_accessor :array
def initialize(source_array)
@array = source_array.dup
end
def current
return EOS if end_of_stream?
array.first
end
def advance
fail "Can't advance past end of stream" if end_of_stream?
array.shift
end
def end_of_stream?
array.empty?
end
end
EOS = Object.new # End of stream constant
def EOS.to_s
"Parser::EOS"
end
EOSMatcher = EndOfStream.new # Matches the end of a stream
end
The above expects an argument to #parse that responds to #advance and #current and #end_of_stream? as demonstrated by the ArrayTokenStream class.
Wednesday, April 12, 2006
Saturday, August 27, 2005
Write ransom notes with Flickr (plus macdevcenter commentary)
Here's a cool place I ran across whilst reading O'Reilly's MacDevCenter. It lets you type in some stuff and it uses Flickr to spell out the letters with various photos. Check it out.
Speaking of MacDevCenter it seems as though there is a dearth of actually macDEVcenter articles on it. I see information about an anti-virus frontend, flickr, an article titled "What is Preview? (and why you should use it)". Now, all these articles contain interesting info, but a lot of them don't actually have anything to do with development. And some of them hint at it, without really delivering.
For instance, the Flickr article describes how to setup and account with Flickr, mentions some Mac tools to use with it, and has a quote by one of the people who wrote a tool extolling the virtues of the Flickr API. However there was no information on this API, no tutorial no sample code, not even a pointer to more documentation. Just the offhand mention of the existence of said API. One would assume that a site like MacDevCenter would be well, targeted towards developers. I suppose I should stop complaining, O'Reilly has a lot of good stuff up there, and he articles aren't bad, and there are some actual developement articles, I just feel like the site name is a bit of a misnomer.
Monday, August 22, 2005
Binghamton 2
Thursday, August 18, 2005
Bing-HAM-ton
Wednesday, August 17, 2005
Dice Rolling Fun in Javascript
<span class="dieroll">1d8</span>in your HTML and $EmerilSoundEffect you've got a clickable die roll, in this case one eight-sided die.
<html>
<head>
<script language="javascript" type="text/javascript">
function addDiceProperties( ) {
var dieElements = getDieElements( );
var x = 0;
for( x = 0; x < dieElements.length; x++) {
dieElements[x].onclick = dieElements[x].onkeypress =
dieRoller(dieElements[x].innerHTML);
}
}
function getDieElements( ) {
var spans = document.getElementsByTagName("span");
var dieElems = [];
var isaDieRoll = /\bdieroll\b/;
for(j = 0; j < spans.length; j++) {
if ( isaDieRoll.test(spans[j].className ) ) {
dieElems[dieElems.length] = spans[j];
}
}
return dieElems;
}
function dieRoller(txt) {
var count;
var sides;
var count_sides = getDieArgs(txt);
count = count_sides[0];
sides = count_sides[1];
return function( ) {
return rollDie(count, sides);
};
}
function rollDie(count, sides) {
var results = 0;
var i = 0;
for(i = 0; i < count; i++) {
results += intRand(1, sides);
}
document.getElementById("resultsbox").value = results;
}
function intRand(mini, maxi) {
var range = maxi - mini + 1;
return Math.floor(Math.random() * range + mini);
}
function getDieArgs(txt) {
var pat = /([0-9]+)d([0-9]+)/;
var res = [];
var match = pat.exec(txt);
res[0] = parseInt(match[1]);
res[1] = parseInt(match[2]);
return res;
}
</script>
<style type="text/css">
.dieroll {
color: blue;
text-decoration: underline;
}
#resultsdiv {
position: fixed;
right: 0;
top: 0;
border-style: dashed;
border-width: 1px;
background-color: white;
padding: 1px 1px 1px 1px;
margin: 1px 1px 1px 1px;
}
#resultsbox {
width: 3em;
}
</style>
</head>
<body onload="addDiceProperties( )">
<div id="resultsdiv">Die Results: <input type="text" id="resultsbox"></div>
<div><!-- This is where the rest of your stuff goes -->
<p>
<ul>
<li><span class="dieroll">1d4</span></li>
<li><span class="dieroll">3d6</span></li>
<li><span class="dieroll">1d8</span></li>
<li><span class="dieroll">1d10</span></li>
<li><span class="dieroll">1d12</span></li>
<li><span class="dieroll">1d20</span></li>
<li><span class="dieroll">1d100</span></li>
</ul>
</p>
</div>
</body>
</html>
EDIT: 5:45PM
Well it seems there are some bugs in the randomness code part. Doesn't look like we ever get natural 20s for instance. I get the feeling it has something to do with the chance of getting a 1 from Math.random( ). So I am going to fiddle with this code, and welcome any suggestions.
EDIT: 8:30 PM
Fixed it. Knew there was something fishy. Thanks to http://www.werelight.com/docs/JavaScript_Quick_Reference.htm
Webcomics Grab Bag
Today I'm going to give you all some links to some web-comics. And by you all, I mean no one. Never the less, here they are:
This is my bread and butter as far as web-comics go, and everyone out there probably already knows about it, but hey, who knows.
Another goodie, copious amounts of D&D humor. Speaking of D&D I have a thought for a little javascript which I may post later today or tomorrow.
Cool because everyone from earth has godly powers. Quite possibly one of the most interesting concepts I've ever come across.
Monday, August 15, 2005
Super Smash Brother's Melee Debug Menu
Morgan the Cat
oooooooooooooooooommmmmmmmmmmmmmmmmmm9999999999999999999999uuuuuuuulllllhuuu988
As you can see she's a little repetitive, but has deep insights in the ways of the world. She's like the feline Edward Albee.