I'm sorry if any of this looks funny; I'm new to gnus.
A couple of weeks ago, for my first Common Lisp project, I wrote a
simple game I've played with before. When I first started writing it I
thought I might try to be "discrete" and wrote a bunch of simple,
specialized functions. However, I found I was constantly changing my
mind about how they would work and what I would call them. The game is
simple enough I figured I would get around myself by writing a
"concrete" version where everything was in one function.
Worked great! I found I could concentrate on just getting it to do what
I wanted and after some more fiddling it works more-or-less the way I
want. However, I feel concerned that I need to work on an essential
strategic skill of recognizing when to delegate something to a
function. I also wonder if I don't really get how to code in the
emergent, "bottom-up" way Paul Graham describes.
I'd love to read any general or particular advice about this. For one
thing, I hope to write more complicated programs someday.
As for what I did write, the file is 188 lines so I have refrained from
posting the whole thing here. You can read it here, if you are curious:
http://wobh.org/Projects/StarMaze/starmaze-concrete.lisp
Note to the future: this URL is not likely to to persist.
Looking at what I've got, some delegations seem obvious--wherever I had
to use "funcall" to a lambda defined in those &key args. But I believe
there are probably other areas. I think I see a division of labor in the
looped code, but if I don't have a general need for that pattern, and I
never called on them from more than one place, what use would they be as
separate functions?
Thanks in advance!
--
William Clifford
|
|
0
|
|
|
|
Reply
|
wobh (18)
|
4/8/2011 5:30:39 AM |
|
William Clifford <wobh@yahoo.com> writes:
> I'm sorry if any of this looks funny; I'm new to gnus.
>
> A couple of weeks ago, for my first Common Lisp project, I wrote a
> simple game I've played with before. When I first started writing it I
> thought I might try to be "discrete" and wrote a bunch of simple,
> specialized functions. However, I found I was constantly changing my
> mind about how they would work and what I would call them. The game is
> simple enough I figured I would get around myself by writing a
> "concrete" version where everything was in one function.
>
> Worked great! I found I could concentrate on just getting it to do what
> I wanted and after some more fiddling it works more-or-less the way I
> want. However, I feel concerned that I need to work on an essential
> strategic skill of recognizing when to delegate something to a
> function. I also wonder if I don't really get how to code in the
> emergent, "bottom-up" way Paul Graham describes.
>
> I'd love to read any general or particular advice about this. For one
> thing, I hope to write more complicated programs someday.
>
> As for what I did write, the file is 188 lines so I have refrained from
> posting the whole thing here. You can read it here, if you are curious:
>
> http://wobh.org/Projects/StarMaze/starmaze-concrete.lisp
>
> Note to the future: this URL is not likely to to persist.
>
> Looking at what I've got, some delegations seem obvious--wherever I had
> to use "funcall" to a lambda defined in those &key args. But I believe
> there are probably other areas. I think I see a division of labor in the
> looped code, but if I don't have a general need for that pattern, and I
> never called on them from more than one place, what use would they be as
> separate functions?
Perhaps having a look at some examples would be helpful:
http://www.informatimago.com/develop/lisp/small-cl-pgms/rpsls/rpsls.lisp
http://www.informatimago.com/develop/lisp/small-cl-pgms/solitaire.lisp
http://www.informatimago.com/develop/lisp/small-cl-pgms/playtomo-stonedge/index.html
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
pjb (7647)
|
4/8/2011 8:09:23 AM
|
|
WC> Worked great! I found I could concentrate on just getting it to do what
WC> I wanted and after some more fiddling it works more-or-less the way I
WC> want. However, I feel concerned that I need to work on an essential
WC> strategic skill of recognizing when to delegate something to a
WC> function. I also wonder if I don't really get how to code in the
WC> emergent, "bottom-up" way Paul Graham describes.
There is no single right way to code.
But I hope you recognize that it might be a bit hard to follow logic flow in
your huge-ass function.
So try to find self-contained parts which can be separated away and move
them out of the large function.
Bottom-up programming does not mean that you should start with simple
functions. You can just start writing your "main" function and in process of
that once parts become large and unruly you can factor them out into a
separate functions.
WC> Looking at what I've got, some delegations seem obvious--wherever I had
WC> to use "funcall" to a lambda defined in those &key args.
Note that you can define local functions with labels/flet.
WC> But I believe there are probably other areas. I think I see a division
WC> of labor in the looped code, but if I don't have a general need for
WC> that pattern, and I never called on them from more than one place, what
WC> use would they be as separate functions?
Improved readability. When you return to this things monthes later and
decide to change something if it is written in a modular fashion you can
easily find what part to work with.
Otherwise you'll have to read the whole thing.
|
|
0
|
|
|
|
Reply
|
udodenko (1040)
|
4/8/2011 10:13:41 AM
|
|
"Pascal J. Bourguignon" <pjb@informatimago.com> writes:
> William Clifford <wobh@yahoo.com> writes:
(snip blah-blah-blah)
>
> Perhaps having a look at some examples would be helpful:
>
> http://www.informatimago.com/develop/lisp/small-cl-pgms/rpsls/rpsls.lisp
> http://www.informatimago.com/develop/lisp/small-cl-pgms/solitaire.lisp
> http://www.informatimago.com/develop/lisp/small-cl-pgms/playtomo-stonedge/index.html
Thank you.
I've noticed that David Lovelace has significantly expanded his
rock-paper-scissors game.
http://www.umop.com/rps.htm
--
William Clifford
|
|
0
|
|
|
|
Reply
|
wobh (18)
|
4/8/2011 2:36:23 PM
|
|
On 04/08/2011 01:30 AM, William Clifford wrote:
> I'm sorry if any of this looks funny; I'm new to gnus.
[...]
> Looking at what I've got, some delegations seem obvious--wherever I had
> to use "funcall" to a lambda defined in those &key args.
One thing that DOES look funny is your use of &key args to define local
variables that should not be arguments. Keyword arguments are used to
allow the user (or in general, the caller of your function) to pass
non-default values for any subset of them when desired. In your case, do
you really want your users to be able to run your code with a different
value for 'axes', or for the 'look' function? LET is probably a more
natural choice in this case.
> But I believe
> there are probably other areas. I think I see a division of labor in the
> looped code, but if I don't have a general need for that pattern, and I
> never called on them from more than one place, what use would they be as
> separate functions?
As someone else replied, readability (especially for you), but also ease
of testing (you can try each individual piece without running the whole
thing every time), ease of debugging (in case of errors a backtrace can
show you which piece the error occurred in), reusability (maybe one day
you *will* need one of these functions for some other purpose). An
obvious place to start would be to put the forms that write help
messages, notes, etc, into separate functions.
Finally, a question: what exactly did you mean by "Write this whole game
with format" (the last comment)?
Alberto
--
Give a man a fish and he will eat for one day. Teach him programming,
and he will develop a multi tasking intelligent planning algorithm to
optimize the route of a fleet of deep sea fishing boats, with
real-time GPS tracking, weather satellite link, automatic analysis of
fish market prices, the whole thing controlled by an AJAX-enabled web
interface. In the meantime, he will die of hunger.
|
|
0
|
|
|
|
Reply
|
alb1 (31)
|
4/9/2011 2:18:09 AM
|
|
On 04/08/2011 10:18 PM, Alberto Riva wrote:
> On 04/08/2011 01:30 AM, William Clifford wrote:
>> Looking at what I've got, some delegations seem obvious--wherever I had
>> to use "funcall" to a lambda defined in those &key args.
>
> One thing that DOES look funny is your use of &key args to define
> local variables that should not be arguments. Keyword arguments are
> used to allow the user (or in general, the caller of your function) to
> pass non-default values for any subset of them when desired. In your
> case, do you really want your users to be able to run your code with a
> different value for 'axes', or for the 'look' function? LET is
> probably a more natural choice in this case.
There are also the underused &aux variables for this very purpose.
CLHS 3.4.1.5 Specifiers for &aux variables
> Finally, a question: what exactly did you mean by "Write this whole
> game with format" (the last comment)?
Don't diss format. It is probably Turing complete if you stare hard
enough... ;)
As to the original question, it is helpful to read different
literature and talk to people to learn different techniques. But the
only way to gain experience is through practice. Write lots of code.
Don't worry about reuse on most of it. Refactor things as problems
arise, and you will quickly find yourself saying "if only I had done
it that other way".
Also, Lisppaste is a great place to post code for others to review.
http://paste.lisp.org/
- Daniel
|
|
0
|
|
|
|
Reply
|
dherring1 (548)
|
4/9/2011 3:27:11 AM
|
|
AR> One thing that DOES look funny is your use of &key args to define local
AR> variables that should not be arguments.
Yup, he should have used &aux for this.
|
|
0
|
|
|
|
Reply
|
udodenko (1040)
|
4/9/2011 12:11:24 PM
|
|
Alberto Riva <alb@nospam.ufl.edu> writes:
> On 04/08/2011 01:30 AM, William Clifford wrote:
>> I'm sorry if any of this looks funny; I'm new to gnus.
>
> [...]
>
>> Looking at what I've got, some delegations seem obvious--wherever I had
>> to use "funcall" to a lambda defined in those &key args.
>
> One thing that DOES look funny is your use of &key args to define
> local variables that should not be arguments. Keyword arguments are
> used to allow the user (or in general, the caller of your function) to
> pass non-default values for any subset of them when desired. In your
> case, do you really want your users to be able to run your code with a
> different value for 'axes', or for the 'look' function? LET is
> probably a more natural choice in this case.
It happens that I did want to be able to change the parameters of the
game as much as possible, but point taken nonetheless. Another poster
suggested using &aux.
> Finally, a question: what exactly did you mean by "Write this whole
> game with format" (the last comment)?
Two parts joke, one part challenge to myself to learn format better.
Thank you!
--
William Clifford
|
|
0
|
|
|
|
Reply
|
wobh (18)
|
4/9/2011 6:40:26 PM
|
|
On 04/09/2011 02:40 PM, William Clifford wrote:
> Alberto Riva<alb@nospam.ufl.edu> writes:
>
>> On 04/08/2011 01:30 AM, William Clifford wrote:
>>> I'm sorry if any of this looks funny; I'm new to gnus.
>>
>> [...]
>>
>>> Looking at what I've got, some delegations seem obvious--wherever I had
>>> to use "funcall" to a lambda defined in those&key args.
>>
>> One thing that DOES look funny is your use of&key args to define
>> local variables that should not be arguments. Keyword arguments are
>> used to allow the user (or in general, the caller of your function) to
>> pass non-default values for any subset of them when desired. In your
>> case, do you really want your users to be able to run your code with a
>> different value for 'axes', or for the 'look' function? LET is
>> probably a more natural choice in this case.
>
> It happens that I did want to be able to change the parameters of the
> game as much as possible, but point taken nonetheless. Another poster
> suggested using&aux.
&aux and LET are essentially the same thing, so the choice between them
would be based only on readability. Putting things in the lambda list
that are not really arguments (ie, they can't be changed by the caller)
is another thing that looks pretty funny these days. There's a reason
why they're underused... :)
>> Finally, a question: what exactly did you mean by "Write this whole
>> game with format" (the last comment)?
>
> Two parts joke, one part challenge to myself to learn format better.
Well, now I'm curious.. is your idea to write the whole thing as one big
FORMAT? :) That would be interesting...
Alberto
--
Give a man a fish and he will eat for one day. Teach him programming,
and he will develop a multi tasking intelligent planning algorithm to
optimize the route of a fleet of deep sea fishing boats, with
real-time GPS tracking, weather satellite link, automatic analysis of
fish market prices, the whole thing controlled by an AJAX-enabled web
interface. In the meantime, he will die of hunger.
|
|
0
|
|
|
|
Reply
|
alb1 (31)
|
4/9/2011 9:32:25 PM
|
|
William Clifford <wobh@yahoo.com> writes:
> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>
>> William Clifford <wobh@yahoo.com> writes:
> (snip blah-blah-blah)
>>
>> Perhaps having a look at some examples would be helpful:
>>
>> http://www.informatimago.com/develop/lisp/small-cl-pgms/rpsls/rpsls.lisp
>> http://www.informatimago.com/develop/lisp/small-cl-pgms/solitaire.lisp
>> http://www.informatimago.com/develop/lisp/small-cl-pgms/playtomo-stonedge/index.html
>
> Thank you.
>
> I've noticed that David Lovelace has significantly expanded his
> rock-paper-scissors game.
>
> http://www.umop.com/rps.htm
Thanks. Now I just have to translate the HTML graph he gives into a
sexp to update my program. Grrr SGML! (So I guess that's a Rock hand
gesture).
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
|
|
0
|
|
|
|
Reply
|
pjb (7647)
|
4/10/2011 10:30:09 AM
|
|
Pascal J. Bourguignon wrote:
>
> Perhaps having a look at some examples would be helpful:
>
> http://www.informatimago.com/develop/lisp/small-cl-pgms/rpsls/rpsls.lisp
Using Scheme:
(define (check-for-winner choice1 choice2 hierarchy)
(let* ((tmp (member choice1 (append hierarchy hierarchy)))
(worse (take (cdr tmp) (truncate (/ (length hierarchy) 2)))))
(if (equal? choice1 choice2)
#f
(if (member choice2 worse)
choice1
choice2))))
(define *hierarchy*
'(lizard paper spock rock scissors))
(define (test c1 c2)
(write (list c1 c2))
(display ": ")
(display (check-for-winner c1 c2 *hierarchy*))
(newline))
(test 'paper 'paper)
(test 'paper 'rock)
(test 'paper 'scissors)
(test 'lizard 'paper)
(test 'scissors 'rock)
(test 'lizard 'paper)
(test 'lizard 'spock)
(test 'lizard 'rock)
(test 'spock 'scissors)
(test 'spock 'rock)
(test 'spock 'paper)
=== output ===
(paper paper): #f
(paper rock): paper
(paper scissors): scissors
(lizard paper): lizard
(scissors rock): rock
(lizard paper): lizard
(lizard spock): lizard
(lizard rock): rock
(spock scissors): spock
(spock rock): spock
(spock paper): paper
|
|
0
|
|
|
|
Reply
|
w_a_x_man (2779)
|
4/11/2011 1:03:07 AM
|
|
WJ wrote:
> Pascal J. Bourguignon wrote:
>
> >
> > Perhaps having a look at some examples would be helpful:
> >
> > http://www.informatimago.com/develop/lisp/small-cl-pgms/rpsls/rpsls.lisp
>
> Using Scheme:
>
> (define (check-for-winner choice1 choice2 hierarchy)
> (let* ((tmp (member choice1 (append hierarchy hierarchy)))
> (worse (take (cdr tmp) (truncate (/ (length hierarchy) 2)))))
> (if (equal? choice1 choice2)
> #f
> (if (member choice2 worse)
> choice1
> choice2))))
>
> (define hierarchy
> '(lizard paper spock rock scissors))
>
> (define (test c1 c2)
> (write (list c1 c2))
> (display ": ")
> (display (check-for-winner c1 c2 hierarchy))
> (newline))
>
>
> (test 'paper 'paper)
> (test 'paper 'rock)
> (test 'paper 'scissors)
> (test 'lizard 'paper)
> (test 'scissors 'rock)
> (test 'lizard 'paper)
> (test 'lizard 'spock)
> (test 'lizard 'rock)
> (test 'spock 'scissors)
> (test 'spock 'rock)
> (test 'spock 'paper)
>
> === output ===
>
> (paper paper): #f
> (paper rock): paper
> (paper scissors): scissors
> (lizard paper): lizard
> (scissors rock): rock
> (lizard paper): lizard
> (lizard spock): lizard
> (lizard rock): rock
> (spock scissors): spock
> (spock rock): spock
> (spock paper): paper
Using Gambit Scheme:
(include "~/srfi-1-reference.scm")
(define pascalistic
'(
(gun targets rock)
(gun shoots at sun)
(gun guns fire)
(gun destroy scissors)
(gun chips axe)
(gun shoots snake)
(gun shoots monkey)
(gun shoots woman)
(gun shoots man)
(gun targets tree)
(gun shoots cockroach)
(gun shoots wolf)
(dynamite outclasses gun)
(dynamite explodes rock)
(dynamite smoke blots out sun)
(dynamite starts fire)
(dynamite explodes scissors)
(dynamite explodes axe)
(dynamite explodes snake)
(dynamite explodes monkey)
(dynamite explodes woman)
(dynamite explodes man)
(dynamite explodes tree)
(dynamite explodes cockroach)
(nuke outclasses dynamite)
(nuke outclasses gun)
(nuke incinerates rock)
(nuke has power of sun)
(nuke starts massive fire)
(nuke incinerates scissors)
(nuke incinerates snake)
(nuke incinerates axe)
(nuke incinerates monkey)
(nuke incinerates woman)
(nuke incinerates man)
(nuke incinerates tree)
(lightning defuses nuke)
(lightning ignites dynamite)
(lightning melts gun)
(lightning splits rock)
(lightning storm blocks sun)
(lightning starts fire)
(lightning melts scissors)
(lightning melts axe)
(lightning strikes snake)
(lightning strikes monkey)
(lightning strikes woman)
(lightning strikes man)
(devil casts lightning)
(devil inspires nuke)
(devil inspires dynamite)
(devil inspires gun)
(devil hurls rock)
(devil curses sun)
(devil breathres fire)
(devil is immune to scissors)
(devil is immune to axe)
(devil eats snake)
(devil enrages monkey)
(devil tempts woman)
(dragon commands devil)
(dragon breathes lightning)
(dragon lived before nuke)
(dragon flosses with dynamite)
(dragon is immune to gun)
(dragon rests upon rock)
(dragon blots out sun)
(dragon breathes fire)
(dragon is immune to scissors)
(dragon is immune to axe)
(dragon spawns snake)
(dragon chars monkey)
(alien varporizes dragon)
(alien does not believe in devil)
(alien shoots lightning)
(alien defuses nuke)
(alien defuses dynamite)
(alien force-fields gun)
(alien varporize rock)
(alien destroys sun)
(alien fuses fire)
(alien force-fields scissors)
(alien force-fields axe)
(alien mutates snake)
(water is toxic to alien)
(water drowns dragon)
(water blesses devil)
(water conducts lightning)
(water short-circuits nuke)
(water douses dynamite)
(water rusts gun)
(water erodes rock)
(water reflects sun)
(water puts out fire)
(water rusts scissors)
(water rusts axe)
(bowl contains water)
(bowl shapes craft of alien)
(bowl drowns dragon)
(bowl blesses devil)
(bowl focuses lightning)
(bowl encases core of nuke)
(bowl splashes dynamite)
(bowl splashes gun)
(bowl once made of rock)
(bowl focuses sun)
(bowl snuffs out fire)
(bowl covers scissors)
(air tips over bowl)
(air evaporates water)
(air chokes alien)
(air freezes dragon)
(air chokes devil)
(air creates lightning)
(air blows astray nuke)
(air blows out dynamite)
(air tarnishes gun)
(air erodes rock)
(air cools heat of sun)
(air blows out fire)
(moon has no air)
(moon is shaped like bowl)
(moon has no water)
(moon houses alien)
(moon shines on dragon)
(moon terrifies devil)
(moon is far above lightning)
(moon is too far for nuke)
(moon sufficates dynamite)
(moon shines on gun)
(moon shines on rock)
(moon eclipses sun)
(paper papers moon)
(paper fans air)
(paper mache bowl)
(paper floats on water)
(paper disproves alien)
(paper rebukes dragon)
(paper rebukes devil)
(paper defines lightning)
(paper defines nuke)
(paper encases dynamite)
(paper outlaws gun)
(paper covers rock)
(sponge soaks paper)
(sponge looks like moon)
(sponge uses pockets like air)
(sponge cleans bowl)
(sponge absorbs water)
(sponge intrigues alien)
(sponge cleanses dragon)
(sponge cleanses devil)
(sponge cleanses conducts lightning)
(sponge cleans nuke)
(sponge soaks dynamite)
(sponge cleans gun)
(wolf chews up sponge)
(wolf chews up paper)
(wolf howls at moon)
(wolf breathes air)
(wolf drinks from bowl)
(wolf drinks water)
(wolf chases alien)
(wolf outruns dragon)
(wolf bites heiny of devil)
(wolf outruns lightning)
(wolf "WOLF-2" launches nuke)
(wolf outruns dynamite)
(cockroach sleeps in fur of wolf)
(cockroach nests in sponge)
(cockroach nests between paper)
(cockroach is nocturnal with moon)
(cockroach breathes air)
(cockroach hides under bowl)
(cockroach drinks water)
(cockroach stows away with alien)
(cockroach eats eggs of dragon)
(cockroach makes man devil)
(cockroach hides from lightning)
(cockroach survives nuke)
(tree shelters cockroach)
(tree shelters wolf)
(tree outlives sponge)
(tree creates paper)
(tree blocks moon)
(tree produces air)
(tree wood creates bowl)
(tree drinks water)
(tree ensnares ship of alien)
(tree shelters dragon)
(tree imprisons devil)
(tree attrackts lightning)
(man plants tree)
(man steps on cockroach)
(man tames wolf)
(man cleans with sponge)
(man writes paper)
(man travels to moon)
(man breathes air)
(man eats from bowl)
(man drinks water)
(man disproves alien)
(man slays dragon)
(man exorcises devil)
(woman temps man)
(woman plants tree)
(woman steps on cockroach)
(woman tames wolf)
(woman cleans with sponge)
(woman writes paper)
(woman aligns with moon)
(woman breathes air)
(woman eats from bowl)
(woman drinks water)
(woman disproves alien)
(woman subdues dragon)
(monkey flings poop at woman)
(monkey flings poop at man)
(monkey lives in tree)
(monkey eats cockroach)
(monkey enrages wolf)
(monkey rips up sponge)
(monkey rips up paper)
(monkey screeches at moon)
(monkey breathes air)
(monkey smashes bowl)
(monkey drinks water)
(monkey infuriates alien)
(snake bites monkey)
(snake bites woman)
(snake bites man)
(snake lives in tree)
(snake eats cockroach)
(snake bites wolf)
(snake swallows sponge)
(snake nests in paper)
(snake is nocturnal with moon)
(snake breathres air)
(snake sleeps in bowl)
(snake drinks water)
(axe chops snake)
(axe cleaves monkey)
(axe cleaves woman)
(axe cleaves man)
(axe chops down tree)
(axe chops cockroach)
(axe cleaves wolf)
(axe chops sponge)
(axe slices paper)
(axe reflects moon)
(axe flies through air)
(axe chops bowl)
(scissors is sharper than axe)
(scissors stabs snake)
(scissors stabs monkey)
(scissors cuts hair of woman)
(scissors cuts hair of man)
(scissors carves tree)
(scissors stabs cockroach)
(scissors cuts hair of wolf)
(scissors cuts up sponge)
(scissors cuts paper)
(scissors reflects moon)
(scissors swishes through air)
(fire melts scissors)
(fire forges axe)
(fire burns snake)
(fire burns monkey)
(fire burns woman)
(fire burns man)
(fire burns down tree)
(fire burns cockroach)
(fire burns wolf)
(fire burns sponge)
(fire burns paper)
(fire heaths campfire by light of moon)
(sun is hotter than fire)
(sun melts scissors)
(sun melts axe)
(sun warms snake)
(sun warms monkey)
(sun warms woman)
(sun warms man)
(sun feeds tree)
(sun warms cockroach)
(sun warms wolf)
(sun dries up sponge)
(sun shines through paper)
(rock shareds sun)
(rock pounds out fire)
(rock smashes scissors)
(rock chips axe)
(rock crushes snake)
(rock crushes monkey)
(rock crushes woman)
(rock crushes man)
(rock blocks roots of tree)
(rock squishes cockroach)
(rock crushes wolf)
(rock crushes sponge)))
(define (order-symbols symbols outcomes)
(if (< (length symbols) 2)
symbols
(let ((pivot (first symbols))
(rest (cdr symbols)))
(receive (better worse)
(partition (lambda (x) (member (list x pivot) outcomes))
rest)
(append (order-symbols better outcomes)
(list pivot)
(order-symbols worse outcomes))))))
(define (convert-to-hierarchy outcomes)
(let* ((outcomes
(map
(lambda (x) (list (first x) (last x)))
outcomes))
(symbols (delete-duplicates (map first outcomes))))
(order-symbols symbols outcomes)))
(pp (convert-to-hierarchy pascalistic))
=== output ===
(sponge paper
moon
air
bowl
water
alien
dragon
devil
lightning
nuke
dynamite
gun
rock
sun
fire
scissors
axe
snake
monkey
woman
man
tree
cockroach
wolf)
|
|
0
|
|
|
|
Reply
|
w_a_x_man (2779)
|
4/11/2011 9:59:53 AM
|
|
|
11 Replies
49 Views
(page loaded in 0.198 seconds)
|