Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: Dwarfputing like it's 2013! The shift register and other components  (Read 10606 times)

Larix

  • Bay Watcher
    • View Profile

This thread is a collection of minecart computing devices of wildly varying size, complexity, usefulness and seriousness. Most of them were completed during last year and haven't been presented at all, or only in the immense slush pile of the "What's going on in your fortress?" thread.

Contents:
This post: twelve-bit shift register, implemented as pseudo-random RNG.

Water level gauge, universal bit-compare gate, improved powerless memory cell, ternary counter cell NEW!! binary incrementer, fully synchronous device-toggler NEW!!

Optimised mechanical adder/subtractor, 16 bit

Powerless, waterless (i.e. perpetual-motion minecart logic) memory bank, capacity eight bytes, two bytes installed.

Bridge toggler (powerless minecart logic)



Spoiler: what is this? (click to show/hide)

This thing up there is a twelve-bit one-directional push register (unless i got the terminology wrong, but that's what i'll be calling it unless corrected). Each bit is represented by one minecart, but currently, the memory is empty, all carts sit in the southern "waiting queue", waiting for input.



Spoiler: instant pushery (click to show/hide)

The register itself is the easy part of this thing. Making it so it can be operated reasonably is harder. It took me a bit to iron out the bugs and stupid errors, but these are the controls:





I am quite pleased to have successfully built something that can be considered a proper pseudo-RNG, independent of game-provided randomness.

I don't expect a 12-bit-based pseudo-RNG arbitrarily wired without further thought to provide a randomness that'd hold up to any rigorous standards. Nonetheless, this push register design could be used for stuff like scrolling text, if you don't mind building and assigning one minecart for every pixel you wish to paint.
« Last Edit: March 29, 2014, 07:33:51 am by Larix »
Logged

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register
« Reply #1 on: January 03, 2014, 10:32:15 am »

Ah yes, shift register is the proper name. Thanks.

Of course, i've done some more stuff in this fort.

Measuring the depth of a single tile of water:




Universal logic gate:



Another crack at a properly writeable memory cell.




Spoiler: spin memory (click to show/hide)

And as an alternative use for my "collision brake", a ternary counter:

     

This uses the rules of minecart collisions to count to three, automatically returning to start on the third signal.


This is nowhere near the most compact design. The door, if it's at all needed (e.g. when using long-lasting signals as input), can simply be stationed on top of the crossing, which would reduce the track layout by two tiles:


But even that is not the smallest you can do. The smallest workable design with a door that i can think of requires six tiles of track and one wall, without a door, another tile of track could be dropped. Even four tiles of track should be possible, but would require "pre-processing" the input signal so that the roller's only active for a few steps.

But wait, that's not all! As a special service for our faithful readers, we add, free of charge... sorry, got a bit carried away there. At the cost of compactness, this basic circuit can be expanded to be an incrementer-decrementer.
Spoiler (click to show/hide)

Or if three is too much to handle, you can of course use the tried and proven collision method for a binary counter, based on stuff like the newton's cradle memory cell. The first solution path i took is basically the same fourpotatoes used and posted in Bloodbeard's minecart computing thread (look here, it's an all-around good read), just cleaner and moderner. Because it looked so nice, i'll preserve the circuit schematic, but i came up with a better, still collision-based binary incrementer, so the explanation will be scrubbed.

Code: [Select]
.WW
╔╝╚╗     sSS╗
║║║║     nCcn
╔╚╝╗     N10N
W..W

Neat.

However, for a small, uncomplicated, reliable incrementer, we need nothing fancier than a slightly expanded collision memory cell:

Code: [Select]
              aaABbb
#======#     #RD^^DR# 

Track. :P      Constructions

R - roller pointing inwards
D - Door
^ - pressure plate triggered by track vehicle

a - devices linked to pressure plate A (roller via un-toggled gear assembly, door directly)
b - devices linked to pressure plate B (same logic as for plate A)

One cart starts on its pressure plate, the other on the roller. Doors start out closed.

Both doors are in addition linked to the input signal you want to count. Apart from the data output from the pressure plates, no further linkages are required.

Spoiler: Operation (click to show/hide)

If regulated by doors, both the binary and ternary incrementer should also be able to count signals from different inputs, as long as they're sufficiently spaced - no new input can be usefully processed before 100 steps have passed.

"Can i link two doors to a lever so that a pull opens one and closes the other?" is a question that has popped up time and again. Of course, the answer is yes, but the link cannot be done directly, it takes an intervening logic machine sending two different signals. The basis of this is still fairly trivial, but thanks to the refractory period of pressure plates, it'd give a lever that opens one door and closes the other one hundred steps later. This is unacceptable, a proper toggle makes them change state at the same time. And with "at the same time", i mean in the exact same tick. Always.

     

It takes two minecarts on a collision circuit, but works perfectly. The actual output signals are sent by the northern pressure plates, the northerly cart is sitting on the eastern of those plates, holding one door open. The cart in the southern half sits on a roller pushing south, paired in opposite phase with the easterly roller (also pushing south). When the lever is switched, the western cart is accelerated, goes around the southern track, pushes the northern/eastern cart and comes to rest on the paired, currently inactive roller, ready to go back on the next lever pull.

The northern/main signal cart goes along the northern track and lands on the western, west-pointing roller there. This roller receives power through a pair of gear assemblies linked to the pressure plates in the southern loop, so is currently inactive. Only after both plates have timed out, the gear assemblies re-engage and the roller gets power again. At this juncture, the cart is pushed off the roller to the west, to the western signal plate. This opens the linked door, and at the exact same moment the other signal plate resets and closes the other door. On the next lever pull, the southern cart will return back west, pushing the signal cart onto the eastern roller (pushing east).

I had to fiddle with this setup quite a bit, but eventually reached the perfect same-tick toggle. I'm pretty certain that build order is important (carts, gear assemblies, pressure plates and doors all have their build times and order can get very zany), and low-speed rollers in the middle are required to get the proper delay from roller activation to pressure plate signal. The south-pushing rollers in the southern track are both highest speed.

This design can be built easier by powering the middle rollers through the signal plates themselves, dropping the plates on the southern loop. This gave me two steps where both doors were closed on every round, but saves quite a bit of machinery and finagling with build order.

The main weakness of this design is that doors open/close ~115 steps after the lever is pulled. That's a fair bit of latency, but getting synchronicity is otherwise quite difficult, because of the pressure plate reset time. A faster toggler could be built by using one full-scale blast door setup for each door, necessitating ~300 mechanisms for something that toggles one pair of doors, with a latency of just under 10 steps optimally. Would be quite an achievement, so if you feel motivated, go for it!
« Last Edit: February 26, 2014, 01:49:24 pm by Larix »
Logged

Quietust

  • Bay Watcher
  • Does not suffer fools gladly
    • View Profile
    • QMT Productions
Re: Dwarfputing like it's 2013! The push register
« Reply #2 on: January 03, 2014, 10:43:39 am »

I've never heard of a "push register", but what you're describing sounds exactly like a shift register (and the type used for random number generators is a linear feedback shift register).
Logged
P.S. If you don't get this note, let me know and I'll write you another.
It's amazing how dwarves can make a stack of bones completely waterproof and magmaproof.
It's amazing how they can make an entire floodgate out of the bones of 2 cats.

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #3 on: January 04, 2014, 08:06:14 am »

And now a return to the old staple of dwarven computing: simple algebra, i.e. adding up.



This is the control panel. It's all binary and takes two sixteen-bit numbers as input, so is not overwhelmingly practical. So let's run it: enter two big numbers, pull the marble lever, make some tea while waiting for the calculation to---



That was, what, about 130 steps after pulling the marble lever? Looks correct anyway. All result bits go active almost instantly, you just need to wait a bit over 100 steps for the incorrect bits to switch off again.

I wonder what the rutile lever by the doors to the left does?



Ah, it subtracts and displays the negative number. It's delivered just as promptly as the addition result.

Well, that's a lot of calculation power. How much floor space must this contraption take?



That much. 8)
That's the whole sixteen-bit adder/subtractor with included binary complement generation for display of negative numbers. All signals displayed on the control panel are generated here, by minecart power-to-signal converters.

Spoiler: workings (click to show/hide)

The whole thing takes up 18x14 tiles, including the bracing walls at the borders. Power consumption in operation is a bit over 200 usually, although just under 400 should be possible.
« Last Edit: January 04, 2014, 04:57:15 pm by Larix »
Logged

CyberUrist

  • Bay Watcher
  • Nothing satisfies—Attain liberation with vigilance
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #4 on: January 04, 2014, 02:50:44 pm »

That's... freaking AWESOME. Do you have a world download?
Logged
Slog looks overjoyed at this revelation.
Slog is a barrel of endless dopamine.

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #5 on: January 04, 2014, 05:02:46 pm »

I could upload the fort with the shift register, water gauger and the memory cells. The adder is in another fort and that one's a complete shambling monstrosity with a boatload of weird engineering experiments all over the place, crawling along at about 20fps on a cheap desktop. Both forts are completely overrun with tame animals, and both are pure tinkering forts, with invaders off and no defensive infrastructure whatsoever.

Not to mention i'd have to put some notes on stuff. Preferably in english.
Logged

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #6 on: February 12, 2014, 09:15:20 pm »

To avoid making another thread, i'll just put it here.

Even more idle messing about, this is the blueprint for a powerless, fluid-less adressable memory. I carved out the floor plan and installed the basic controller and operation machinery for eight bytes, but only actually installed two. Which are two more bytes than i actually have use for, this thing's utterly pointless by itself.




So, what's this prove? Well, for one that powerless minecart logic is comparable to other logic disciplines in its scope. This thing here is a memory bank that can be adressed by "register index", holds information indefinitely and can be written/cleared/read via simple commands using two or three levers. The read output can be held indefinitely as well. On the downside, it demonstrates that larger minecart logic devices work fairly slowly and the more complicated pieces of machinery tend to be either powerful _or_ compact _or_ reliable, getting two out of three is already pretty rare. This contraption is well over half the size of Jong's memory banks in the dwarven computer and holds only a quarter as much memory. The controller circuit is massively sub-optimal because i just went in blind and cobbled it together as i thought about it, but i don't think it'd be possible to get it _much_ smaller than this.

At least the powerless latch is pretty compact and elegantly simple, at 10x1 tiles.
« Last Edit: February 13, 2014, 10:27:14 am by Larix »
Logged

Nil Eyeglazed

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #7 on: February 14, 2014, 02:11:01 am »

That's amazing.

Are you doing more?  Do you have an instruction set planned?  I love this stuff.

I'm seeing fewer than 15 tiles per bit.  Is Jong's really twice as compact as that?  Never looked at his map, but wasn't he using over-under water pump cells?  That should come to 16ish tiles per bit.  And addressing should add another 8ish: two z-levels full of pumps, and one z-level full of gears.

How slow is it running?  It sounds like it should be doing 400-tick instructions, getting everything read or written inside the space of a resetting bridge-- is that right?  Doesn't strike me as slow in the least.  Of course, it's hard to compete with the ease and speed of addressable memory via gear grid.

I have to admit, it's very difficult to work out what's going on (especially since I'm not a minecarter yet).  Do you happen to have, say, two bits of addressable memory someplace?  Working along the same principles?  Less to get confused by.  For instance, was trying to see how scalable it would be, but can't find the doors.
Logged
He he he.  Yeah, it almost looks done...  alas...  those who are in your teens, hold on until your twenties...  those in your twenties, your thirties...  others, cling to life as you are able...<P>It should be pretty fun though.

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #8 on: February 14, 2014, 07:59:55 am »

Thanks! It's fun to play with this sort of stuff, but i'm still not sure where i'm going in the longer run.

Space consumption is 18 tiles per bit on each level. The level below holds all the bottom halves of all those ramps, required to actually move the carts. Jong's cells come out as 2x5 tiles per bit (because they can share walls), spread over a few more levels, but some of the space on the neighbouring levels could be used for other purposes and a dwarf should be able to walk through everything but the water-holding tiles without harm during operation. Not so with minecarts.

The basic principle of the memory cell is shown a bit more closely in my second post on this thread, it's the last of the devices i was rambling about, although it's not exactly the design i settled on. The important thing is that the actual bit input is sent to the hatch just _next_ to the one the cart is standing on in the "off/inactive" position, i.e. the input to _all_ say, fifth bits of all bytes within the memory bank is operated by the same lever and pressure plate, but has no effect if the "write" signal is not sent (to this very byte). "Write" and input signals also have no effect on an "on" memory cell, because the cart's in the central loop, away from the input/write pit.

I've endeavoured to delve into the foundations of this kind of powerless minecart signal processing on my wiki user page - http://dwarffortresswiki.org/index.php/User:Larix/MPL but that'd be a very long read and much of it is probably either too basic to warrant explanation, too byzanthine to warrant talking about or too clumsily worded to be understandable (or a combination of those three). It absolutely doesn't help that i have no prior computing education, and i don't mean the "i only know how to program in visual basic lol" 'uneducated'; i barely know that a thing named Visual Basic exists and it took me until today to even understand what the various steps in Jong's testing program actually did and what the hell the PC and IR and whatnot in there actually are.

Looking at the design, hmmyeah, there's no indication where the controller loop actually starts - the cart is dropped from simple hatch cover into an accelerator pit to start on its round, goes through three yes/no gates according to the "adress" input to find the path corresponding to the byte that it's supposed to operate on, _then_ goes through another binary switch (via bridge) to determine whether to write to the byte or clear the byte, _then_ sends the actual operation signal and finally returns to the starting point, where the hatch has closed in the meantime, so the cart's ready for a new command the moment it returns. The starting/end point is that solitary hatch cover in the northwestern corner with a pressure plate just south of it and two (NW) track corners to the east. Pathing direction through the loop is counter-clockwise (i often forget that it might need mentioning - it's my standard sense of rotation and that regularly gets reflected in my constructions).

Obvious issue: i've thrown adressing and instruction into the same circuit - to avoid building an extra control loop for every memory manipulation action, i made this single circuit more complicated to house write, clear, and clear-with-read all at once. The memory bank itself could be expanded at the cost of a bigger control loop with longer performance times, but i think using a "master control" interface to adress multiple separate memory banks would eventually be the better option.

Time - hmm, tricky. The "write" performs fairly quickly, since it's just a single flick of eight hatch covers. Depending on the byte adressed, it takes from just under 200 to probably a bit over 300 steps to perform. "Clear" takes a similar time but "read" is much slower. It first has to wait for 100 steps+ for the buffer to clear first, then introduces another ~100 step wait period from sending the 'clear' until making the latches in the buffer responsive. Add to that the pathing times until the clear is sent and the return time to the starting location, and it's probably well over 400 for a full read.
The time the cart needs to path through the adressing hatch-pits varies by byte chosen: a cart takes under ten steps to pass a ramp-pit in a straight line, but if the hatch is closed, the cart takes 15 steps to emerge on the entrance side, and then has a longer path to move around and get to the next pathing decision in line, i'd say we're looking at ~15 vs. ~35 steps per gate, so 45 to 105 steps to decode a three-bit adress. This does not bode well for synchronicity. It could be improved by using bridges-over-corners for switching instead, as long as the cart starts out with enough speed to make it through without getting overly sluggish. Edit: no wait, since both the cart's path _to_ the signalling plates and the paths from those plates back to the start are variable, a more uniform timing would give the paths with the most "off" address signals the shortest return paths and vice versa. I think that'd already remove much of the differences and put all "write" signals in the 250-step range.

The fact that reads only occur as a side-effect of clearing the byte suggest that this should be reflected in an instruction set as well - i.e. try to build programs with as few reads as possible and keep in mind that each read empties the adressed byte, you'll need an extra "write from buffer" to restore it.

On the whole, since the programmable computer has already been done and proven functional, i feel like i'll have to find a niche or application that's new and interesting first. This kind of minecart logic probably _could_ build a conventional programmable computer, but it'd be slower, buggier, bigger and more dangerous than the dwarven computer that already exists. Considering how sanity-endangering that project already was, i'm not really considering building something even insaner to produce a much inferior repeat of a prior achievement.

I think the memory cell itself, while it has its quirks, is a viable (compact, powerless) design.
« Last Edit: February 14, 2014, 04:03:54 pm by Larix »
Logged

gtaguy

  • Bay Watcher
  • {Curly Brace}
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #9 on: February 14, 2014, 01:46:16 pm »

How do I make a NOR gate?
Logged
Quote from: GoldenShadow
I don't understand why you need magma.
Quote from: Duuvian
Well done OP, you've inadvertently weaponized ghosts.

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #10 on: February 14, 2014, 04:00:16 pm »

Most easily with mechanical logic:

Code: [Select]
PabO

P=power source (gear assembly, axle, pump, roller...)
a,b = gear assemblies linked to data input
O=output, e.g. a power-to-signal converter, the pump you want to activate when the condition is met...

The gears will be engaged when no input is active and will toggle, i.e. disengage and stop transporting power, when receiving an input. Only if both inputs are off, power will get from the power source to your output.

A NOR gate can also be built under other logic systems - two raising bridges in a row for fluid logic (fluid gets through if both bridges get an "off" signal, lowering them), two hatch covers over empty space for goblin logic (goblin can pass if both hatches are "off" and closed) or, trivially, minecart pathing logic (although there are better designs for the latter), the "ground" path of a pet-logic OR gate. If you have sufficient power (say, a whaterweel farm), mechanical logic is always the smart option - quick, configurable, safe, FPS-friendly.

Oh, in case you meant with this logic discipline - the one i've put on the wiki is pretty much what Di said. Check two hatch-pits, make the pathing so that the pressure plate can only be reached if both hatches are closed. My current favourite, however, is this one:

     

Uses nothing but two retracting bridges. Cart comes from the south, the southern bridge is over engraved floor with no track. Carts coming from track will dive into a pit with track ramp, carts coming from non-track treat it as an ordinary hole and jump over it. Bridges count as track, so you can toggle the entrance behaviour between "track" and "non-track" by toggling a bridge. If both bridges are "off", i.e. extended, the cart dives into the pit, can't leave because the exit is blocked by the northern (2x1) bridge, returns south and goes around the corner to the east where a pressure plate would collect the "NOR" signal. The funny thing with this gate is that it can turn all four possible inputs from a bit pair into four different ouputs with just two signal-operated buildings. Should make it useful for decoding binary input, but incidentally also makes it a universal two-bit logic gate if you add the necessary pressure plates to it.

Late re-edit: and if the thrust of the question was "can you really build serious logic with this kind of stuff, e.g. a 'NOR-Latch', which consists of two NOR gates?" the answer is "that's the wrong question" :P
The NOR-Latch, as i understand it, is one way of building an S/R-Latch. If you want a settable/resettable memory cell, what matters is that it can perform the desired actions, not that it contains two NOR gates. And Bloodbeard's "Newton's cradle memory cell" does exactly that. Add another pressure plate, and you even have a proper "cell has been reset" output. And the bank of eight memory cells in my memory bank making up the buffer? Each of them's an S/R latch with added 'enable set' switch. Building these kinds of things from NOR gates would be possible, but massively overcomplicated and wasteful.
« Last Edit: February 16, 2014, 09:46:36 am by Larix »
Logged

Di

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #11 on: February 14, 2014, 04:25:32 pm »

How do I make a NOR gate?
Something like:
|tracks back to start|output plate|input hatch A|track|input hatch B|cart entrance
|ramp back to start|wall|ramp back to start|wall
Cart enters from the right, if at least one hatch is open, it doesn't reach the pressure plate.
It's easy really. Unlike the stuff latrix built up there.
Logged
Quote from: Creamcorn
Dwarf Fortress: Where you meet the limit of your imagination, moral compass, sanity and CPU processor.
http://www.bay12forums.com/smf/index.php?topic=103080.0 Fix sober vampires!
http://www.bay12forums.com/smf/index.php?topic=91442.0 Dwarven Cognitive Science

Nil Eyeglazed

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #12 on: February 14, 2014, 04:55:47 pm »

Yeah, forgot you need the slopes penetrating the z-level below-- leaves you with a space that's hard to use for computing.

Still, I can't imagine Jong's really at 10 tiles/bit?

Code: [Select]

 ##
 .#
 %#
 %#
 .#

Even reusing walls, that's 10 tiles per z-level per bit, with another z-level necessary below, then a third z-level scattered with reservoir pockets...  Not to mention space required by addressing, power transfer, power....  You do realize that all of those memory cells need multiple z-levels per bit, right?  I think you have Jong beat for space requirements.

Quote
I've endeavoured to delve into the foundations of this kind of powerless minecart signal processing on my wiki user page - http://dwarffortresswiki.org/index.php/User:Larix/MPL but that'd be a very long read and much of it is probably either too basic to warrant explanation, too byzanthine to warrant talking about or too clumsily worded to be understandable (or a combination of those three). It absolutely doesn't help that i have no prior computing education, and i don't mean the "i only know how to program in visual basic lol" 'uneducated'; i barely know that a thing named Visual Basic exists and it took me until today to even understand what the various steps in Jong's testing program actually did and what the hell the PC and IR and whatnot in there actually are.

It's really funny-- I'm looking at your user page right now, and I basically worked along the same path as you, but for creature logic (http://dwarffortresswiki.org/index.php/User:vasiln if you want to read my own basic and byzanthine explorations of DF computing, lol).

Super, totally mind-blowing, because like you, I've never really studied computers, and it was always kind of a mystery to me how they went from "here's an xor circuit" to "here's photoshop, tada!"  Creating addressable memory, an adder, (bit shift, conditional jump, etc), I started to see exactly how these things translate to useful, real world stuff.

I'll check it out in more depth later-- kind of hanging out since I see a big new release is coming, but don't really want to fire up DF until then.  Got your user page open though, see if I can puzzle any of it out lol :)
« Last Edit: February 14, 2014, 04:58:36 pm by Nil Eyeglazed »
Logged
He he he.  Yeah, it almost looks done...  alas...  those who are in your teens, hold on until your twenties...  those in your twenties, your thirties...  others, cling to life as you are able...<P>It should be pretty fun though.

Larix

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #13 on: February 14, 2014, 05:29:27 pm »

Heh, your user pages have been a source of encouragement for me more than once. It didn't cut out any of the learning process to me, what counted was that they demonstrated that there's quite a lot of potential in DF logic, and it all starts with very basic concepts.

I must say this kind of powerless logic is a bit of a pet thing of mine, i discovered it purely by accident. I had tried out using hatch covers as (vertical) switches for powered minecarts, because of the instant reaction to signals, and in one of the circuits, a cart wouldn't stop moving when it fell into a two-ramp pit. Everything else spiralled from this discovery. The big flaw with this logic discipline is of course that it's based on buggy behaviour of minecarts on track ramps, so i'd better get my major projects on it finished before things get fixed ;)

Concerning memory cell size - this design _may_ be a bit smaller on the memory cells themselves when compared to the classic double-pump fluid cell when counting the spread over multiple levels, especially when keeping in mind the need for fluid and power infrastructure. It loses where speed and synchronicity are concerned, and the powered minecart switches by Bloodbeard et al. are definitely smaller, although for proper read-/write adressing, those might pick up a lot of weight for the needed switch gears.
Logged

Nil Eyeglazed

  • Bay Watcher
    • View Profile
Re: Dwarfputing like it's 2013! The shift register and other components
« Reply #14 on: February 20, 2014, 03:23:30 pm »

oops double somehow, scroll down
« Last Edit: February 20, 2014, 03:30:04 pm by Nil Eyeglazed »
Logged
He he he.  Yeah, it almost looks done...  alas...  those who are in your teens, hold on until your twenties...  those in your twenties, your thirties...  others, cling to life as you are able...<P>It should be pretty fun though.
Pages: [1] 2