Sign in to follow this  
  • entries
    16
  • comments
    27
  • views
    15391

About this blog

My milkshakes bring all the boys to the yard.

Entries in this blog

Conner McCloud
That's the conclusion I've reached. After jumping through dozens of hoops to finally get everything to a point where it pretty much works as you'd expect, they light one of the hoops on fire and put it over a shark tank. And the sharks have fricken lazers on their fricken heads.

Basically, as my recent post in the .Net forum has mentioned, I've discovered you can't apply operator++ to unnamed temporaries. I don't know if that's the proper word for it or not, but essentially it means ++container.Begin() is invalid. This mostly makes sense, but it doesn't seem like something that would be impossible to overcome. Just create an unnamed temporary that is immediately discarded, no big deal.

That wouldn't be quite so big a deal except for this: the C# compiler isn't smart enough to know that its against the rules. Instead, it spits out invalid code that, at run time, throws a nasty exception. The situation is slightly better if Begin is a read-only property instead of a function --- then, the compiler crashes when it sees the code. So at least you know in advance something is wrong, rather than silently emitting invalid code, even if a compiler error would be more appropriate.

So what, exactly, does this mean for the SGL? Well, it could well mean that I'm done. Things like for(Iterator i = ++vec.Begin(); i != vec.End(); ++i) are not exactly uncommon in my code. I certainly can't imagine a more straight forward way of skipping the first element in a container. Technically, I could use vec.Begin().Advance(1), but that's ugly. Seriously, I can't stand it; my test code is littered with it, and every time I write a loop I die a little inside.

And more importantly, the compiler won't stop me, or anybody else, from using the first form. It'll just happily spit out invalid code that'll cause the program to choke when executed. That's unacceptable.

Perhaps I should buckle down and learn C++/CLI. Perhaps, since that is perfectly valid C++ code, it will also be perfectly valid C++/CLI code. And the whole project will be saved. I doubt it, though. I'm a little too tired to be optimistic at this stage.

CM
Conner McCloud
Conceptually, what is the difference between a Sequence and a Sorted Container? Answer: The fact that you specify the order of a sequence, while the sorted container decides on its own where to put things. Its a bit of a simplification, but overall I think that really sums it up.

With that in mind, having Insert(i, x) being defined for a Sorted Container simply doesn't make sense. More importantly, expecting a function that relies on Insert(i, x) to work properly on both Sequences and Sorted Containers doesn't make sense.

So, this is the final breakdown I have decided on:

Container -> ErasableContainer -> ISequence -> IRandomAccessSequence
-> IBackSequence
-> IFrontSequence
-> ISortedContainer

Unfortunately, this makes for a system that is rather verbose. List, for instance, is an ErasableContainer, an ISequence, an IBackSequence, and an IFrontSequence all at once. Vector is slightly better, being an ErasableContainer, an IRandomAccessSequence, and an IBackSequence. Stack would simply be a Container, but it would accept an IBackSequence as a parameter.

This is what I meant when I said a couple posts back that the hardest part of working with Containers is figuring out what to inherit from. At some point, I would like to sit down and see if I can't come up with something a little less clunky by dropping the STL association. But I doubt I will.

Once I have actually finished making these changes [they aren't substantially different from what I had originally], I think I'll go ahead and publish a version 0.1. I'll be leaving out all the SortedContainers, because they're in a rather broken state, but I do have both List and Vector, as well as quite a few standard algorithms. So there's still plenty to laugh at.

Until next time.

CM
Conner McCloud

On containers

When designing my iterators, I pretty much just went to the C++ standard [chapter 24, Section 1: Iterator Requirements], and copied it. That worked great, the end results were quite pleasing.

Initially, I did the same thing with the containers. In fact, I did the same thing with containers before I even did it with iterators. However, I now realize this was rather silly. There's a lot of duplication in the definitions of sequences and associative containers. For instance, the only Sequence methods that aren't also in Associative Containers are insert(p, n, t) and insert(p, i, j) [erase(q) and erase(q1, q2) are present in both, but have different return values ... I must admit I don't understand why].

Theoretically, this isn't that big a deal; you can just duplicate the definitions. This is exactly what I did initially. However, then generic algorithms can't work on both Sequences and Associative Containers except via iterators, even if they are restricted to the common interface. See, for instance, insert_iterator. In C++ that works with both types, but C# requires a common type that defines the insert(p, i) method.

So should that common type exist? If so, should it do all of the common methods?

What I'm leaning towards now is inserting a ModifiableContainer type between Container and Sequence/Associative Container. Right now, Container is pretty much read only, and I figure that's a pretty useful distinction to have. So adding a second layer with the inserts and erases makes sense to me. But then I wonder if the extra complexity is justified, and if I shouldn't just put it all into the base Container type. Or maybe even make it completely orthogonal...right now I have a BackInsertSequence type that defines PushBack, PopBack, and Back; why not have an InsertSequence type that defines Insert and Erase?

Bah, explicit type constraints are making this a lot harder than it needs to be [sad] It was so much nicer when I could let the C++ standards committee do my design for me. Now I'm going to have to sit down and draw out exactly what I want everything to be capable of, and what I don't want them to be capable of, and go from there. Uber boring.

CM
Conner McCloud

Generic cycling

In the wake of the untimely demise of my car, I've lost my will to do much of anything other than play Baldur's Gate, a game I find entertaining but ultimately rather klunky and poorly executed. Being without a television, however, its all I've got to satisfy my need for some role playing action.

I've been feeling the itch to code, however, and so I'm going to give a quick update on the SGL in the hopes that it'll push me over the edge and I'll start back up again.

It turns out that learning generics at the same time as designing a complicated series of generic containers wasn't that good an idea. The whole equality issue I encountered is a prime example of why: I did it right initially, but a misunderstanding in how generics work resulted in my replacing my correct Equals functions with incorrect versions that still did the job. I later corrected my misunderstanding, but the incorrect Equals remained. Later attempts to perform trickery then failed, because Equals wasn't implemented right, and I concluded that such trickery was impossible when in reality it was quite trivial to fix.

All told, creating those writeups last week were a god send. They made me realize how shoddy my initial design was, and I have since cleaned it up quite a bit. The actual use of the iterators remains largely unchanged, but now you can do this:


void function(RandomAccessIterator begin, RandomAccessIterator end)
where Itr : RandomAccessIterator
{
//Some algorithm specialized for RandomAccessIterators
}

void function(BidirectionalIterator begin, RandomAccessIterator end)
where Itr : BidirectionalIterator
{
//Same algorithm, but using the more generic BidirectionalIterator
}


By doing this, I have also made it possible for the compiler to infer all the type arguments on its own. To see why, consider what the functions would have been before:


void function(Itr begin, Itr end)
where Itr : BidirectionalIterator
{
//All I can do is use the Bidirectional version, no random access optimizations :(
}


In both versions, the function has two generic parameters, T and Itr. When infering those parameters, the compiler only looks at the actual function arguments...it doesn't consider the where clauses. In the second version, T is only present in the where clause, so the compiler has to be told explicitly what type to subsitute in. Now that I can specify the specific type of iterator directly [rather than delegating it to the where clause], that is no longer an issue.

The other change this has made possible is the addition of iterator adaptors. For instance, I now have a BackInsertIterator that mimics the behavior of std::back_insert_iterator. How it works will have to wait for another day, though, since I haven't gotten to the chapter on generic containers.

Why not? Because when I went to write up that section, I realized my containers were a horrible mess. I wrote them first, so that I had something to iterate over, but the radical changes to my iterator design only propagated backwards so far as was neccessary to keep things compiling properly. The end result was a nightmare, with a horrible hodgepodge of classes and interfaces and general crap that needs to be gotten rid of.

If this post does the trick, it should only take a day or so to get right. Then we can continue our discussion of the SGL.

In the mean time, I need to figure out some way to get snazzy screenshots out of this project so that my journal is a little less boring.

CM

*edit: PS, I've implemented a bunch of the generic algorithms required by the C++ standard. I'm rather proud of the fact that I can actually copy the code from an actual implementation, fix the stylistic differences [* -> Value, in particular], and end up with a fully working function. I don't, of course, because that would be stealing, and most of them are near impossible to read anyhow. But the fact that I could makes me feel all proud of my little generic iterators.
Conner McCloud
First of all, if you at all enjoyed Super Troopers, go see Beerfest right now. I have never in my life heard an entire theater laughing uncontrollably at the same time until this movie. I have heard individual people laugh, and had the occasional "ha ha ha ha done" laugh pass through the croud, but this was full force "I can't breath" laughter. This movie is awesome enough that it could share some of the funny with Club Dread and end up with two good movies afterwards.



So, when last we met, I had given you an overview of some of the high level decisions I had made. In the interim, snk_kid was kind enough to point out just how pointless this project really is: Dinkumware is working on STL/CLR, and it will be included with VS at some point in the near future. But that's OK. I'll bet I'll have SGL finished first, so when I'm done I'll forward them a copy for inspiration [wink]

Today, I would like to get down into the nitty gritty details of how everything actually works up to this point.

We will begin with iterators, because they were the hard part. The C++ iterator library defines five classes of iterators:

RandomAccess -> Bidirectional -> Forward -> Input
-> Output

All iterators support forward movement via operator++, so you can consider enumerations to be a form of InputIterator1. I have chosen to follow suit, and make use of the same heirarchy. I somewhat regret not making OutputIterator independant of the basic chain, but fixing that now would be non-trivial.

In C++, this heirarchy is largely imagined...you specify what type of iterator you are using the iterator_category tag, but otherwise a BidirectionalIterator is simply one that defines operator-- in addition to operator++. In C#, such behavior would not work...generic types and methods depend on inheritance to see what behavior is and is not allowed. For this reason, I define six types:

  • interface InputIterator -- specifies a read-only property Value

  • interface OutputIterator -- specifies a write-only property Value

  • abstract class Iterator -- Implements operator++, Advance, and Distance in terms of the abstract method Increment(), and implements operator== in terms of Equals.

  • abstract class ForwardIterator -- Derives from Iterator, InputIterator, and OutputIterator. Provides no additional functionality, and leaves the Value property abstract.

  • abstract class BidirectionalIterator -- Adds an abstract method Decrement, and implements operator-- in terms of it. Also adds support for using operator- in place of Distance2, and overrides the default Advance to allow for negative values of n.

  • abstract class RandomAccessIterator -- Adds an abstract indexer (essentially operator[]) that allows constant time movement of the iterator. Implements operator+ and operator- (when used with integral operands) and overrides the default Advance to make use of the indexer.

Now, lets say you are implementing an iterator for an iterator for a List class [err..LinkedList class...damn .Net calling arrays lists [flaming]]. In this case, you would want to inherit from BidirectionalIterator. In order to get all the functionality of a BidirectionalIterator you only have to provide five functions: self equality via Equals, the Value property, Increment, and Decrement. That's it...everything else you need is provided transparently by the underlying classes. If you were implementing Vector.Iterator, you would inherit from RandomAccessIterator, and provide the same functions, plus the indexer.

So what about using them? That's just as straight forward. Just decide what type of iterator you are working with, and go from there. As an example, here's a hypothetical implementation of for_each:

delegate void Function(T v);
void for_each(Itr begin, Itr end, Function f)
where Itr : Iterator, InputIterator
{
for(; begin != end; ++begin)
f(begin.Value);
}

//Later, within some function:
List l;
for_each(l.Begin(), l.End(), delegate(int v) {System.Console.Write("{0} ", v);});

If you implementing Sort, which requires RandomAccessIterators, then you would simply replace the where line above with where Itr : RandomAccessIterator, and you'd be free to use begin[5] or end[-10].



Now, as I mentioned, there is a rather significant problem with the overview I just gave. Namely, overloaded operators don't work that way. In .Net, overloaded operators are static functions...this means you can't inherit them, and the return value is permanantly stuck with one type. You would not think this would be a problem, because even if dealing with a base class the virtual functions would still call the proper methods. And indeed, I am now entirely unable to recreate the bugs I encountered at the time.3 However, the combination of inheritance, generics, and overloaded operators resulted in some subtle bugs, especially with regards to equality. Sometimes, they could be gotten around with simple casts to the proper type, but not always.

The solution I found was the Curiously Recurring Generic. Observe:

class Iterator {
public static Iterator operator++() {/*implement me*/}
}

class VectorIterator : Iterator {}

Becomes

class Iterator where Itr : Iterator {
public static Itr operator++() {/*implement me*/}
}

class VectorIterator : Iterator> {}

Now, all the operators operate on the derived class instead of on the base class, even though the operator itself is defined in the base class. It is really quite slick, I think.

This recurence goes all the way up, with ForwardIterator, BidirectionalIterator and RandomAccessIterator all accepting the same second parameter. Only InputIterator and OutputIterator, which only define a property that doesn't care about the actual iterator in any way, are exempt.

This is not without its pitfalls, of course. In addition to making the definition of iterators slightly more complex, it seriously hinders the ability of the compiler to infer types automatically. You have to parameterize based on iterator, because you can not have a BidirectionIterator, for example, on its own. If it isn't obvious why, try it out:

void SomeFunc(BidirectionalIterator
void SomeFunc(Itr iterator) where Itr : BidirectionalIterator

C# does not look at the constraints list when infering parameters, so it has no way of knowing what type to assign to T. This means you have to specify it every time:

SomeFunc.Iterator>(l.Begin());

As you might imagine, that gets annoying rather quickly. I have identified two ways to help it along. The first is for when I'm lazy:

void SomeFunc(Itr iterator, T placeholder)

The placeholder is just there to put T into the argument list so that C# can figure things out on its own. Obviously, this is not an ideal solution. The alternative is much cleaner:

static class Algorithms {
void SomeFunc(Itr iterator) where Itr : BidirectionalIterator {}
}

//later, to use it:
Algorithms.SomeFunc(l.Begin());

You still have to specify T, but that is typically fairly straight forward. It is the Itr parameter that you don't want to be bothered with. So while still not ideal, it is at least marginally easier to work with.4



I think that pretty much brings us up to speed on Iterators. Unfortunately, I got distracted a few times and now I have to work in an hour, so Containers will have to wait. They are pretty straight forward, however, and there are no real complications with their use.

The last thing I'd like to do is show how one can use iterators in practice. Namely, I'm going to show off the code that allows an iterator range to be used in a foreach structure. I stripped the comments, because they were in the XML format MS likes, and that made it a bit verbose for such a simple structure. I added a few where neccessary.

public class RangeEnumerator
: IEnumerator, IEnumerable
where U : Iterator, InputIterator
{
public RangeEnumerator(U begin_, U end_) {
begin = begin_;
end = end_;
}

IEnumerator IEnumerable.GetEnumerator() {
return this;
}

public System.Collections.IEnumerator GetEnumerator() {
return this;
}

public bool MoveNext() {
//Enumerations start one before the begining of the range, so itr
// itr being null signifies that position.
if(itr == null) {
itr = (U)begin.Clone();
return itr != end;
}
itr++;
return itr != end;
}

public T Current {
get {
if(itr == null || itr == end)
throw new InvalidOperationException();
return itr.Value;
}
}

Object System.Collections.IEnumerator.Current {
get {
//Is it possible to somehow use the other form of Current for
// this? I should probably yank both bodies into a separate
// function.
if(itr == null || itr == end)
throw new InvalidOperationException();
return (Object)itr.Value;
}
}

public void Reset() {
itr = null;
}

// I don't know what this function is for, but I get yelled at if it
// isn't here.
public void Dispose() {
}

private U itr;
private U begin;
private U end;
}

//This is a helper class that allows the compiler to infer the two type
// parameters. It occurs to me now that I could possibly move
// RangeEnumerator into this class and simplify things a bit.
public static class Range
{
public static RangeEnumerator Create(U begin, U end)
where U : Iterator, InputIterator {

return new RangeEnumerator(begin, end);
}
}


This is how you actually use them:

class Program
{
public static void Main(string[] args) {
//I know we haven't covered vectors yet, but I'm use you can figure out what this does :)
Vector<int> v = new Vector<int>();
for(int i = 0; i < 10; i++)
v.PushBack(i);

foreach(int i in new RangeEnumerator<int, Vector<int>.Iterator>(v.Begin(), v.End()))
System.Console.WriteLine(i);

//Or, more simply:
foreach(int i in Range<int>.Create(v.Begin(), v.End()))
System.Console.WriteLine(i);

//Although it is not the point of the code, you can also do this:
foreach(int i in v)
System.Console.WriteLine(i);
}
}


As an aside, when I finished typing out that demo program I pressed B.

And with that, I bid you fare well.

CM

1This is a bit of a simplification...you are only allowed to read from an input iterator once [this restriction is lifted by ForwardIterator], but you can reset an enumerator and pass through it multiple times if you like.

2I have to look through my notes to see if there's a reason why this functionality is provided by BidirectionalIterator and not by Iterator itself...the actual implementation is simply rhs.Distance(lhs), so there's no reason why it wouldn't work with ForwardIterators as well.

3The fact that I can't recreate the bugs, despite them being quite obvious at the time, bothers me. This calls into question all the decisions I have made since. I think over the next couple days I will try and work backwards and recreate the problems I had before. Hopefully, it wasn't just a misunderstanding that I have since rectified. I fully understood the source of the problems at the time, but I was learning a lot at the time so you never know.

4There is a third option I just now tried out:

void SomeFunc(BidirectionalIterator iterator) where Itr : BidirectionalIterator {}

In that case, it infers both parameters just fine. However, equality doesn't work right. As I mentioned before, equality is the area that was most severely affected by the issues that lead to implementing the recusion in the first place. I know exactly how to fix it, and I'm willing to bet that doing so will lead me to remember what caused the bugs in the first place. So that is where I shall begin my search.
Conner McCloud

Happy Panda

Windows is back. Hooray! It was even easier than I thought it would be...I envisioned losing all my data and having to reinstall all my software, but all it took was putting in the new harddrive, loading it with the ghost I made before things went up in smoke, and performing a repair installation of Windows.

So now I'm back to work on Super Awesome Library 5000. Or possibly STL.Net. Or maybe SGL. I haven't decided yet. Its pretty close to being at a point where I would feel comfortable showing off actual code, but not quite. I think I'm going to finish up with the basic algorithms and maybe implement a deque, and then release a demo version before I do any hard work on the sorted containers [although I have a basic Set class put together, it is pretty ugly and doesn't quite work yet].

In the mean time, I'm going to give a basic overview of the project as a whole, and some of the design decisions I've made along the way.

First of all, let me make it clear that this was a project born of boredom. Neccessity may be the mother of invention, but boredom is the drunk uncle that nobody really likes. It basically started because I was a little annoyed that enumerators in .Net don't allow you to modify the values you are enumerating. I missed my iterators, but realized that given the behavior of .Net generics iterators wouldn't work anyhow. But then one day I got bored [my internet broke down so I couldn't play WoW, and I have no television] and decided that I would go ahead and try to implement iterators anyhow. I knew I would fail, but I had nothing better to do with my time.

As luck would have it, I succeeded. Or somewhat succeeded...it was rudimentary, but a good proof of concept. My internet was still down, so I figured what the hell...why not just go all the way and recreate the whole shebang? Now, its evolved into something I want to do just because I can.

The reason I say all that is because I'm still convincing myself that its OK to reinvent the wheel in this case [embarrass] I'm fully expecting the end result to be slower than the standard counterparts, as well as harder to use in some regards, and probably less safe to boot. And I know it isn't portable as of yet, because mono is incapable of running it [although gmcs does compile it all properly]. But maybe I'll learn something useful1, or people will find it handy. At the very least, I'll have something to chug away at while I'm bored [grin]




So, onto the actual design. To begin with, let me explain where it isn't going to be a straight port, and why.

The biggest difference is that I've decided to omit custom allocators. From a design standpoint, they seem to go against the idea of running in a managed environment. From a practical standpoint, I wouldn't know how to program a custom allocator in .Net anyhow. Also, .Net doesn't allow you to specify default parameters, so you would have to explicitly state that you wanted the standard allocator every single time. This fact is compounded by MSs decision to not implement typedefs in C#, so even that shorthand isn't possible in the language I chose to implement this system in. All together, the decision to remove custom allocators was a pretty easy one to make.

A similar process will probably result in sorted containers not being parameterized on comparators. As I mentioned, I haven't actually completed this portion of things yet, but I will almost certainly go the route of System.Collections.Generic.SortedDictionary, and accept a Comparer object. I haven't quite finished analyzing what effects this will have, however, so the final result remains to be seen.

I am also discarding the SC++L style of using_lots_of_underscores in favor of a more .Net-friendly UsingLotsOfCapitalization.

Iterators are an actual concrete type rather than the abstract pseudo-type they are in C++. In addition to allowing Iterators to work at all within the confines of .Net generics, they allowed me to make Distance and Advance member functions rather than global functions. This is quite important, as I'm pretty sure its the only way functions like std::lower_bound can perform better with vectors than they do with lists. It is impossible to specialize generics, so there can only be one implementation of Advance(itr, n), which would have to be to the effect of while(n--) itr++;. But, itr.Advance(n) can be inherited by a RandomAccessIterator to be just itr += n;2

For obvious reasons, iterators aren't dereferenced via *itr. Instead, a property Value is exposed.

There are no iterator tags, or type-traits, or anything like that, because generics would be completely unable to utilize them. Instead, such information is carried in the inheritance. If you are implementing a BidirectionalIterator, then you inherit from BidirectionalIterator. I suppose that isn't entirely accurate...you can use inheritance in C++ to achieve similar effects, but you don't *have* to. distance_type is always int, and you just have to keep track of value_type on your own3.

Although they do not now, ultimately the containers will all expose .Net-style interfaces. Vector will inherit from IList, and so forth. The primary reason they don't already is because I'm lazy. I'm also torn on whether or not to rename List so it is a little less confusing when mingled in with the standard containers. I suppose naming it LinkedList wouldn't be *that* bad, but that can wait. They do currently inherit from IEnumerable [and its generic cousin] so they can be used with foreach.

I think that pretty much covers the big changes that I'm aware of. Although I used a lot of words to describe them, they're largely superficial and don't really effect how you actually use everything. Implementations are a little odd, but that's something I have to worry about, not you [grin] The weirdness, however, all comes from inheriting from the proper objects. Once you've done that, all the grunt work is done, and you just have to provide three or four implementations so that all the real hard stuff [like overloaded operators, which were a bitch and a half to get working right] is done for you automagically.

I want to move onto implementation details, but I have to work in two hours and honestly, I'm not sure I have the time. Its pretty complex, and I'd rather not just throw the stuff out there without explaining why I did what I had to do. So that can wait for another day.

CM

1 Speaking of learning something, did you know that _ is a valid name in C#? I assume it works in other languages as well, I've just never bothered to try it and see. I'm tempted to write a class named _ and fill it with functions named __ and ___ and ____ just for the hell of it. Unfortunately, this knowledge was learned independant of STL.Net, so I haven't quite justified my time yet.

2 In my last journal entry, I stated the following:
Quote:

The biggest hurdle I think I have left to overcome is how to specialize algorithms for specific types of iterators. Haven't had any inspirations on that front in a while, so I fear it might not happen.

This was only partially true, and was mostly my memory playing tricks on me. I haven't had any inspirations as to how to specialize algorithms...instead, I think making Distance and Advance member functions has allowed me to work around the problem to a certain extent. I forgot about that. It isn't a perfect solution, but its good enough for government work.

3 The lack of a way to specify value_type is, to date, the biggest annoyance I have with this whole system. I say that only half-heartedly, however, as I'm not positive a simple typedef would actually solve any of the problems I associate with the lack of said typedef. It is a conventient scapegoat, though.
Conner McCloud

Sad Panda

A while back I got bored and decided to develop a CLR compliant version of the C++ standard containers library in C#. In particular, I wanted to see if I could get iterators working. So far, my success has been rather promising. I've got Vector and List working, with a rudimentary Set implementation, and my experiments with generic algorithms have proven mostly successful. The biggest hurdle I think I have left to overcome is how to specialize algorithms for specific types of iterators. Haven't had any inspirations on that front in a while, so I fear it might not happen.

However, then my harddrive died, and I got pushed onto my secondary harddrive, which is occupied by Linux. This itself doesn't really bother me. I dislike working on the Dark Side, but Ubuntu is relatively painless, so I just run with it. Eventually, I'll find my missing XP CD and everythign will start coming up Milhouse again.

In the meantime, I caught mono, and spent a fair amount of time figuring out how to work with the 2.0 compiler. Unfortunately, Monodevelop does not support compiling with gmcs, so I'm stuck with make. Again, not that big a deal. I figured it all out, set my project directories up in a nice tidy way, and compiled my test program. It compiled flawlessly, without so much as a warning. I then run the resulting executable.

First, I get a warning: "Implement me." Then, I get an error: "Code should not be reached. Aborting...aborted."

Superb. Apparently, mono's generic support is not quite at 100%, and my [admitedly complicated] use of them falls in the part still left to be finished. Which means I can develop my code, but not test it.

/sigh

CM
Conner McCloud
Life is certainly strange. Some fourteen months ago, I was graduating from a respected university with two sought after degrees. Today, I am posting from a library [twelve minutes left on this session, I had better hurry], preparing for my next shift at a local Dairy Queen.

And I honestly do not remember when I was last happier.

It isn't so much that I enjoy being an assistant manager at Dairy Queen. Although, I do. Very much so. It is more that I have a vision again. A new goal for my life after the last faded years ago to the turmoil of earning those two degrees.

But I am getting ahead of myself, and I am down to eight and a half minutes. No time for dillies, and less time for dallies.

As I said, some fourteen months ago I graduated. I immediately began searching for employment, both with software firms [my first degree being in Computer Science], and with engineering firms [my second degree being in Electical Engineering]. I found employment difficult to find. As the months wore on, I realized the reason employers did not find me attractive was that I myself had little to no desire to work in either field. I love developing software, and I love developing hardware, and I especially love the magical realm where the two disciplines meet. But I simply could not envision myself doing it for a living. They are a hobby to me. A hobby I love, and will always love, but a hobby none the less. Not a career.

But what else could I do? I have, after all, nearly killed myself getting through college, not to mention putting myself rather seriously in debt, all to enter the very fields I was not discarding. I was distraught. It was not a happy couple of weeks as I searched my soul for some sign of what I should do.

Fortune and I have a very healthy relationship, and in this case it did not let me down. At the very same time I was was going through this dilemma, my brother was having trouble with Algebra, and attending study sessions with his teacher and a bunch of other students over the summer. As I was currently unemployed, I volunteered to help out in my spare time. The experience was, for lack of a better word, breathtaking. I felt satisfaction watching those kids grasp math that I never felt writing programs or building robots. It was a satisfaction that I have only felt in passing here on Gamedev, pretending I know enough about programming to help others in the General Programming forum.

It became immediately clear what I am meant to do. Teach. I've heard the jokes from my peers; those who can't, and so forth. I don't really care. This is what will make me happy, I am more certain of that then anything I've ever felt before.

And so I am returning to school. Apparently, to teach high school math requires actual coursework. Not much, of course, since I already have a degree in math. Just a handful of courses in education. And some reading and writing bull shit that the School of Mines never saw fit to officially teach me. I figure I could knock it out in a year, maybe three semesters, if I felt so inclined. But I've done the full time student thing, and I think I want to take a break from it. What's the hurry? I have my entire life ahead of me, and now that I have a goal I can enjoy myself for a while.

And yes, make ice cream for ten dollars an hour. Sure, its not the $40k a year job I was told to look forward to when I left highschool, but it is honest work, I get experience with Teenagers, and five nights a week I get a free meal. Really, what more could a guy want?

And so there you all have it. The quick and dirty summary of where Conner McCloud is. I am sure you have all been dying for an update on my amazing life, and I am more than happy to oblige. And for those of you living in the greater Denver area, feel free to swing by my store. I promise I'll give the brasier guy a stern talking to should he spit in your meal.
Conner McCloud
Before I begin, I want to make something clear. In my entire life, only two books have produced actual physical responses in me. One, The Shining terrified me, and resulted in nightmares for several days. The other, The Hitchhiker's Guide To the Galaxy, caused me to literally drop the book because I was laughing so hard. I don't laugh out loud at comedians, and that's their only reason for being. So to me, that says a lot about the quality of the book.

That was all my freshman year in college. So about five years ago. I didn't have ready access to the other four books, so I never bothered to read them. In the back of my mind, I always planned to.

Enter the movie. I enjoyed the movie. Yes, they cut out a bunch of my favorite lines, but oh well. All in all, I found it thoroughly enjoyable.

Shortly thereafter, I went to buy The Bourne Ultimatum at Barnes and Noble, and happened to pass by The Ultimate Hitchhiker's Guide To The Galaxy. "At last in paperback in one complete volume, here are the five classic novels from Douglas Adams's beloved Hitchhiker series." "Includes the bonus story: 'Young Zaphod Plays It Safe.'" Needless to say, I'm still only two books into the life of David Webb, but a full five into the life of Aurthur Dent.

Naturally, the best place to start a story is at the begining. So I reread "Hitchhiker's", just to make sure i haven't forgotten anything. I didn't laugh out loud this time, but that wasn't the fault of the book. Quite the contrary, it was every bit as entertaining as the first time. I just knew what was coming, and had time to prepare for the particularly funny bits.

So I keep going, plowing headfirst into The Restaurant at the End of the Universe. I didn't laugh out loud this time, either. But I did chuckle a few times. All in all, it was good.

Sadly, that's the last time I can say that about the series.

I'm trying really really hard to come up with redeaming qualities of the last three books. I am, honest Injin. But it just isn't possible. I mean, sure, there were some high points. The story of the fellows from Krikkit first going into space was quite good. The initial explanation about how one learns to fly will likely find its way into my general vocabulary. But halfway through So Long, and Thanks for All the Fish even that has lost its charm.

Before I go on, let me make something perfectly clear. First, yes, I'm an American, raised on American humour. Although, apparently I occasionally spell it "humour." I am completely willing to admit that chances are, I just missed the point. Somewhere, something in my upbringing just made me incompatable with these books. Apparently, there are a lot of people who feel these books are the second coming of Christ. That's cool, I respect that. I'm still going to proceed to explain, in detail, exactly why they're all wrong. I am going to do this knowing full well that it is entirely possible that the fault lies with me.

Now, where was I? Oh, right.

Part of the problem, I think, is one of plot. In various reviews of the theatrical adaptation, many people complained that the plot was overdeveloped. Adams' work isn't about plot, its about characters and comedy and blah blah blah. I believe Superpig refered to the books as the opposite of sitcoms. At the time, thinking about "Hitchhiker's", this made sense. It was just a bunch of random shit happening for no apparent reason. Then the book ended, and you still didn't have an apparent reason. And that was OK, it worked.

Oh, except for all the "Why did I become president and zap my brain and steal this ship" bitching from Zaphod that formed the basis for most of The Restaurant at the End of the Universe. For an author that doesn't care about plot, he sure went out of his way to set himself up for a sequal.

But that was still cool. At first. Then, the "lets just do random shit" kicked back in, and we find ourselves with Ford and Arthur stuck on a prehistoric Earth. But that's not the problem. The problem is that there are also a bunch of telephone cleaners and hair dressers stuck on a prehistoric Earth. Apparently, the very presence of these telephone cleaners and hair dressers is sufficient to cause the native inhabitants to die out. This leads to the natural conclusion that Arthur is decendent from these telephone cleaners and hair dressers. All without the knowledge of the pan-dimensional super intelligent mice that were, supposedly, responsible for the development of Earth.

At this point, Adams officially crossed the line between "random shit" and "completely retarded." Sure, it was a little funny when you find out that the ultimate question is "What is the product of six and nine" [heh heh, six times nine doesn't equal fourty-two, narf], but the underlying stupidity of the whole thing is just too much. Was it really necessary? Did it serve anything to have this revelation?

To a certain extent, yes, it did. It introduced a certain symmetry to the book. You see, for me, the two best parts of The Hitchhiker's Guide to the Galaxy are as follows:

(1) The parallels between Arthur's home being demolished and Arthur's planet being demolished.

(2) The pan-dimensional super intelligent mice that have been controlling our destines for all of history.

So what is the first thing Adams does in The Restaurant at the End of the Universe? Reveal that there are no parallels between Arthur's home being demolished and Arthur's planet being demolished. His home was demolished to make way for a bypass, and his planet was demolished to keep the pan-dimensional super intelligent mice from learning the Ultimate Question to Life, the Universe, and Everything.

What is the last thing Adams does in The Restaurant at the End of the Universe? Reveal that there are no pan-dimensional super intelligent mice. Instead, there's just pan-dimensional idiot mice who apparently don't question the overnight evolution of their experiment from primitive "cave men" to telephone cleaners and hair dressers.

This brings us to Life, the Universe, and Everything. At this point, any claim that Adams doesn't write plot-driven stories goes right out the window. Even seemingly pointless happenings are immediately put to good use in furthering the story. The single biggest example of this is obviously the story about the computer that wants to blow up the Universe. It starts off as an interesting little aside about how you should never try to solve anything with potatoes, and ends up being the crucial bit of information necessary to save the day. Why did Trillian even watch that segment of history? It has nothing to do with anything.

Then there's the fact that Adams is apparently on a crusade to destroy everything that made "Hitchhiker's" entertaining. Many people have speculated that if we knew exactly why the bowl of petunias had thought ["Oh no, not again"] we would know a lot more about the nature of the Universe than we do now. Apparently, many people are wrong. Did the knowledge make that section more entertaining than it already was? No, not at all. Frankly, that was the best section in the book. Did it render one of the more interesting parts of the initial book completely pointless? Yes, absolutely so.

That scene also set up the basis for later plot devices, but we're still a solid book away from that.

The final gripe with Life, the Universe and Everything is the ending. First, there's the nice climactic "oh shit I'm about to detonate the bomb and destroy the Universe, why oh why did I want to play cricket?" moment. This pissed me off to no end. Completely unneccessary. Then, they throw in this Prak fellow who explains that you can't know both the ultimate question and the ultimate answer at the same time. This didn't bother me all, actually, but I feel like pointing out the implied "Fuck off and stop asking me what the god damn question is" that Adams was classy enough not to actually say. Personally, I felt the revelation in The Restaurant at the End of the Universe about Arthur not knowing the question was sufficient to settle that once and for all, but apparently not.

Enter So Long, and Thanks for All the Fish. Now, right off the bat, I recall several people complaining about how Earth was brought back at the end of the movie. If any of these people have read So Long, and Thanks for All the Fish, they are too stupid to breed.

Other than that, I don't have much to say about this one. I wasn't impressed, but nothing particularly horrible happens. At least, not at first. You're well into Mostly Harmless before you realize how crappy So Long, and Thanks for All the Fish is.

I hope, after all I've written thus far, my reasons for disliking Mostly Harmless should be pretty clear. Think about it for a moment while I check out the Lounge really quick. I've been working on this for three hours now, so I need a break.

OK, I'm back.

Before I get into Mostly Harmless I should probably mention the bonus story "Young Zaphod Plays It Safe." I don't understand it at all. I suspect something happened, but I don't know what. There were a few cleverly written bits, so I give it high marks.

Moving on, the single worst thing about Mostly Harmless is the treatment of the Vogons. Up to this point, you have been treated to Vogons that are completely devoid of imagination and generally incapable of any real thought. Hence their knack for beurocracy.

And yet in Mostly Harmless you discover that Captain Prostetnic Vogon Jeltz of the Galactic Hypersace Planning Council manages to mastermind a hostile takeover of the Guide publishers and creates some fancy new Guide that can manipulate space and time. How does that not require imagination and thought? It just doesn't make sense. Sure, there's a certain logic behind Mr Jeltz being obsessed with destroying Earth. But why the overly complex plot?

Fortunately, up to that point the book was actually quite superb. You encounter such wonderful scenes as the heartfelt and emotional goodbye when Fenchurch dies. And the shock and awe that Arthur experiences when he discovers that more than just the one copy of Earth survived. Or the way Adams doesn't even remotely forshadow Arthur's death fifty times throughout the book. Personally, I wouldn't have been able to help but remind the reader every couple pages that Arthur can't die until he gets to Stavro Mueller Beta. After all, this fact wasn't menioned at all in So Long, and Thanks for All the Fish, so its possible they might have forgotten. But then, that's why I'm not a world class author.

No, I didn't like the fact that Adams felt compelled to not only kill off three of the original characters, but to introduce two more just to kill them off as well. But that's OK, I don't have to like every decision an author makes. However, I do expect a certain quality of execution that I don't feel was present in Mostly Harmless.

So there you have it. Conner McCloud's in depth analysis of the complete lunacy of a world in which The Hitchhiker's Guide to the Galaxy trilogy can be heralded as a beaken of literary perfection. Please, feel free to explain to me the various ways in which I missed some point. Perhaps once I'm aware of the point, I will be able to like the series. At the very least, I'd like to look back on the first book with untainted memories, even if I never like the rest.


Actually, I'm not quite done. Being a developers journal I'm going to menion my programming goals. I'm currently working on a card game. In my head, its a fairly generic framework that will simplify the creation of multi-player games. More importantly, it will simplify the creation of AI bots to play these multi-player games. I'm learning wxWindows to do the windowing stuff, but there is also going to be the ability to do it all at the command line. Less overhead for training bots, but with the ability to have a handy interface for humans playing the game as well. Hopefully, I'll have an initial release of a Cribbage game by the end of Summer. Plus maybe Blackjack and Texas Hold'em. Once the graphics stuff is done, creating new games should be a breeze.

CM
Conner McCloud
So I'm down to my last week. Interestingly, I discovered this site early in my first semester [I lurked for several months before registering]. So if you've been paying close attention, you could probably trace how my beliefs and opinions have been changed by the college experience by running through my profile.

But that's not why we're here. We're hear so you can be imparted with some words of wisdom by myself, the smartest man you are likely to come across on the internet in the next couple of minutes.


  1. Unplug things. I can't stress this enough. Being connected to a power supply fucks everything up. For one thing, you can't measure resistance if your circuit is hot. They don't tell you this in intro to circuits, but its true. Also, cutting live wire can be quite dangerous. My eye has never been the same. A more subtle issue is that PC power supplies have power and ground shorted for some reason when the thing is off. So if you're using one for your power, having it connected to your circuit will cause some false positives when doing connectivity tests.

  2. Plug things back in. I can't stress this enough. Not being connected to a power supply fucks everything up. For one thing, you can't measure voltage if your circuit is cold. This is mostly an issue when you're not expecting to see voltage anyhow - ie, you want 0 V, and when you check the voltage you get 0 V, so you assume everything is AOK.

  3. Related to the above: PC power supplies make for great cheap constant voltage sources. They might not be as accurate as a more expensive solution, but I've never found that to be a problem. They can supply massive amounts of current, and should have internal circuitry to protect itself from faults. At least, all the one's I've used have killed themselves rather than be damaged by current spikes. All I had to do was power down and then power back up, and everything was fine.

  4. Get lots of wire, with different colors. A good color scheme can mean the difference between a successful test and a failed one. At the very very least, have a color just for ground. This gives you a quick and dirty way of verifying that you don't have any shorts to ground before following the advice given in (2).

  5. Plan out your layouts in advance. This is one place where nodal analysis comes in handy. If A, B, and C are all attached to a common node, then don't connect A to B and then B to C. Instead, connect all three to some fourth point, and give them all the same color. This makes later bug checking easier, because you've got fewer pointless jumpers lying around just waiting to come unplugged or be forgotten. Instead, each pin has exactly one wire, and you can tell at a glance that A and C are connected without wasting time going through B.

  6. Larger gauge wire is actually smaller. I am forced to assume this is one of two things: a clever reference to the fact that the internal resistivity is larger, or a stupid throwback to the early days of wire sizing. My gut says the latter, but either way 0 is considerably bigger than 30.

  7. Know Ohm's law. Apply it whenever you are about to put a resistor in a circuit. Why is this resistor there? What currents will it be seeing? How much voltage can be dropped across it without causing a problem? And so forth. Some times, like with pull up/down resistors, it doesn't really matter. But sometimes it does. A back of the napkin analysis is sufficient to validate that you aren't doing anything terribly stupid.

  8. Solder is nobody's friend. If solder were an ice cream flavor, it would be pralines and dick. Avoid it whenever possible. Prefer bread boards to just running wires. Prefer wire wrapping to soldering wire. Prefer through hole to surface mount. For prototyping, its just faster. I like to think of soldering as premature optimization. I'm not even sure this circuit is going to function, do I really care that my contacts are 100% solid? Probably not. Obviously, sometimes you know that you need to keep noise to an absolute minimum, or heat requirements require surface mount, or whatever. In those cases you should adjust accordingly.

  9. On your standard Radio Shack wire strippers, that screw allows you to change the size of wire you are stripping. Closer to the cutters allows for thicker wire, closer to the handle allows for thinner wire. Now that you know that, you can stop accidentally cutting your wire because the stripper is expecting a higher gauge.

  10. Many places will give you free samples. Take advantage of this. Microchip and Freescale are both pretty generous.

  11. LabView is very nice. The hardware can be pricey, but I've grown to like it for any sort of transient analysis. It's not quite good enough to replace an oscilloscope for fast circuits, but if you're just calibrating an accellerometer or figuring out how a circuit behaves then it's more than adequate. Plus, graphical langages are just going to get more important in the coming years, so it'll probably be useful to be familiar with some now.

  12. Prefer a pre-built solution to doing it yourself. This is a lot like programming - the STL is right there, why are you designing your own linked list? If you need USB support, just buy a PIC with USB support. Maybe it'll be more expensive, but you've saved yourself the hassle of implementing the interface yourself. Plus, see (10). This applies to more than just high level communications - many common applications have IC solutions available if you look for them.

  13. Understand how capacitors and inductors behave under steady state conditions. Their pictures spell it out - a capacitor has a giant gap between its terminals, so in steady state it is an open circuit. An inductor is a solid line, so in steady state it is a short. This also gives a hint as to their transient behavior. Inductors allow current to flow, so they fight current changes [V = L dI/dt], whereas capacitors have a voltage difference, so they try to maintain a constant voltage [I = C dV/dt].

  14. Always always always double check your resistance values before you insert them into a circuit. This is a thirty second test, and can save you some agrivation when you realize that you transposed two colors and ended up with a resistor a factor of ten smaller than you wanted.


That's all I can come up with. You have officially learned as much as I have in the last five years. Congratulations, and take that fancy diploma.

CM
Conner McCloud
I'm off to take the EIT exam. With any luck, the next time I'm turned down for a job, they'll be turning down an apprentice Engineer rather than a starving college student.

Unfortunately, I'm going to need a lot of luck. I'm going to crash and burn, hard.

CM
Conner McCloud
So I just spent a week building Gentoo. Not quite set up all the way yet, but I'm getting there. I use Gnome because its easier to say than KDE, and after all the hassle building the damn thing, the last thing I want to be worried about is how to pronounce my desktop manager. The whole process wasn't too bad, but I went to sleep with something compiling one night, and had a power outage. Didn't know how to pick up where I left off, so I had to start over. Everything built more slowly the second time around, which confuses me. The kernel in particular too a lot longer. I noticed, because the first time it only took like ten minutes. I was surprised, having been led to believe it should have taken a few hours. The second time, it did take about two hours. I was surprised, experience having shown it should have only taken about ten. I assume I did something wrong the first time.

This is a very specialized thing, I need it for a project that only compiles on VC6 in Windows. Very much a hassle, as I made the upgrade to VC.NET just before Christmas. I was unsuccessful importing the workspaces, and this seemed easier than trying to fix the problem. Of course, I'm not certain it'll wok in Linux either, as i need direct rendering, and apparently my video card requires special drivers. Stupid ATI. Or stupid Linux, or stupid somebody. I haven't decided yet. Whatever the case, I'm still entirely unconvinced that Windows isn't the OS for me, having tried out Gentoo, Fedora, Mandrake, and Ubunto with mostly similar results. So I'll keep this around instead of installing cygwin on Windows. I can't get it to install properly, so this is convenient.

I am officially graduating in May. I was almost one credit short of getting my CS degree, because a professor in the CS department has no soul. But it worked out in the end, so I forgive him. You are all formally invited to attend commencement on 2005 May 13. Weather permitting, it'll be outdoors with limited seating, but there's plenty of standing room in the back. If you like, you can also attend my birthday celebration on 2005 May 11. It shall be a very good week. A birthday, and not one but two silver diplomas.

I have done literally no programming since my last journal update. Finals got in the way, then I went to Phoenix for the holidays where I was without access to my source tree, then I spent a week building a Linux distribution. Lord willing, I'll be able to get some work done this weekend. Video games'll take a hit, but I can live with that.

CM
Conner McCloud
This has been a hellacious couple of weeks. One assignment after another after another. They have a real knack for drowning me in work just when I start to get excited about a personal project.

My favorite assignment is the final project for my Algorithms class. There are three parts: the overall algorithm, preliminary code, and functional code. The first was submitted prior to Thanksgiving, the second on Monday, and the last part is due next week sometime. Without going into too much detail, we came up with a graph representation of the problem, and found a solution that solved it in O(e lg n) time [where e approaches n^2 in the worst case]. We submitted this, and got to work on the preliminary code. We got the algorithm back yesterday: full marks. This despite the fact that this problem is NP Complete. Now, I don't fully understand that subject, but from what I gather if my algorithm is correct, I not only go down in the Computer Science History, I get a rather substantial amount of money.

I'm sure you'll forgive my scepticism.

So we settled on simulated annealing. Which is interesting, because its nothing, at all, like anything we've discussed in class. We're just now covering the subject of NP Completeness, and that's the end of the road. This project is completely tanjent to everything we've done so far, and its worth 20% of the final grade. Not that I mind, I've implemented simulated annealing before. But I was rather proud of my little algorithm, and to just get rid of it hurts. On the inside.

In a similar turn of events, it turns out the method I was going to use for my terrain renderer is a little out of my league as well. In the sense that its not mathematically possible for my method to work, at all. I have a solution in mind, but haven't had the time to implement it, damn them.

I have, however, had time to implement my relay. [Mostly because its a graded assignment, but a win's a win]. It works like a champ. Hotter than all hell, but a small fan [ganked from a PC power supply] fixed that right up. Unfortunately, my coworkers have had almost as much success with the H-Bridge, and we would all prefer a solid state solution if we can get it. Which means my poor relay [like my poor algorithm] will likely be trashed. There's still a chance of failure, though, so there's still hope.

And in my final offshoot, I get to build a transformer next year. No, not the lame kind. The bad ass kind. I'm not 100% clear on the details, but it has to crawl down a 4" pipe, and then turn into a giant rake that cleans a pipe leading out of a septic tank. I was going to call it 'Septicon', but I think that's a little too close to 'Decepticon'. Either way, I have a logo design all planned out. Its in the basic style of the picture on Optimus Prime's shoulder, but its a toilet. If I can make it small enough, it will be my new Avatar.

So, too summarize:
Discovered impossible algorithm ->
discovered impossible equation ->
built a relay for a robot ->
going to build a robot ->
summarization of the above

CM
Conner McCloud

RMAC Champs!

The CSM football team has now won thirteen straight games, and are the RMAC champions for the first time in school history. I don't follow football, but its pretty exciting none the less. And to think, if I were attending a four year school, I'd have graduated already and missed all the fun. We host the first playoff game, I think I'll try to attend.

Yay Orediggers!

CM
Conner McCloud

Failures

Still figuring this stuff out. I think I found most of the stuff yesterday. The default theme is the only good one [no offense to the creators], and I managed to get a simple little avatar. I recieved my first commment [yay Mushu!]. Pretty productive, all things considered.

Today is dedicated to figuring out how to post images, which should double as a good test of the personal webspace feature.



Walking Machine
Although I said yesterday was productive, I lied. I'm like that. In reality, everything I touched failed. In the walking machine arena, despite five hours messing with it, the silly relay never properly switched. Not only did it not switch, but when it did switch the power supply would shut down [its a PC power supply, I assume its got an internal fuse or something that keeps it from catching fire]. If I actually have the motor running, the primary transistor gets hot.

How hot was it?

Let me show you [promised image test]:

That is a standard TO-220 package. There's no scale in the picture, but its about the size of my thumb. How do I know? I have a blister that looks surprisingly like it, and it fills my entire thumb.

In the poor transistor's defense, it didn't melt. I suspect a heat sink will keep it sufficiently cool. Unfortunately, that's under no load. The current's just going to go up from there.

The circuit I actually built was pretty hacked, though. The offending transistor was a P-type FET when the diagram called for an N-type [no big deal, I modified the circuit appropriately], and I accidentally used a FET instead of a BJT elsewhere in the circuit [big deal, as I did not modify the circuit appropriately]. Later today, I hope to get hold of a Basic Stamp to give me proper signals, and rebuild the thing using the right parts. Hopefully, it'll work this time.

I was going to try and post these pictuers imbedded, but they're big and I don't know how to make them thumbnails. So here's links instead. Isometric and overhead views of the walking machine. Keep in mind that I had no part in the design [this project is in its fifth year, and I just started in August], and two of the legs are missing.


Hex Terrain
I did some more coding on the isometric engine, and for some reason I can only call new twice before it starts returning null. This is our concern Dude. I sat at my computer for about three hours, running the program over and over again hoping that if I got the exception enough times, it would eventually start working. It didn't. Stupid deterministic compilers. Stupid Microsoft insists on putting out a program that produces the same code no matter how many times you compile the source. Damn them to hell.

So I played Final Fantasy 7 until 3 AM. Its been years [7, I believe], since I played this game. I thought perhaps it would suck less the second time through, but it doesn't. If somebody could please explain to me why, exactly, Cloud didn't cut Cait Sith's balls off, I would appreciate it.

CM
Conner McCloud
So I found the money to support Mother GameDev, and so I have done so. Now I'm figuring out how to use all the cool stuff I have access to.

I do plan on using this as a project journal, so I'll go ahead and introduce myself first. I am Conner McCloud [not of the Clan Macleod, so don't ask], and I am better than you. I don't hold that against you, of course. I understand that its not your fault I'm so great. [grin]

Seriously, I go by Dennis Zickefoose, Junior, in the real world. I am a duel Computer Science and Electrical Engineering major at The Colorado School of Mines. By my count, there are two students and one alumna hanging around GDNet. Its nice to know I'm not alone. With any luck [and its currently looking pretty good], I'll be joining the alumni ranks come May.

I have a number of projects I'm working on, but two in particular I figure I'll be discussing here over the course of the next couple weeks.

(1) The Walking Robot. This is my Senior Design project required for my Engineering degree. Its about three feet by two feet, it has six legs, and walks like a crab. Or would, if it didn't suck. I'll post a picture once I figure out how. I am currently focused on building motor drivers, which is a lot harder than it sounds. The motors are real beasts, and draw up to six amps when starting, and two amps when running freely. All cheap, commercial solutions fry pretty much instantaneously. I've spent the semester designing a high current H-Bridge, but when the motor stalls one of the FETs activate, creating a short to ground and melting half of the circuit. If you're not familiar with electronics, in lay terms this is a bad bad thing. The other day, however, I came upon Building Robot Drive Trains. This is a wonderful book, which I highly recommend to anybody dabling in robotics. In my case, the important thing is that there's a design for using mechanical DPDT relays in lieu of a solid state h-bridge. I'm about to go into the lab and build one, and if it works I'm going to push for its use. They don't share my worries regarding our current design, so its going to be a tough sell as we're about to buy the components to build lots of our broken drivers.

(2) This one is somewhat more Game Development-ish, although I have no current plans of actually fleshing it out into a full fledged game. Its a Hexagon based tile sysem, with support for hills and such. It was a good excuse to learn D3d9, and so far I must say that I'm impressed. I remember dabbling with D3d7, and get getting frustrated and going back to DDraw. Either I know more, or the API has gotten cleaner. I suspect its a combination of both. Either way, I can already tile the screen with hexagons, and manipulate the camera and such. So my next step is to figure out the terrain. I'm developing it all from scratch rather than reading stuff on known solutions, so it should be interesting to see how it turns out. That work should progress this weekend.

And so there we have it. My first journal entry. I should have been at school forty-five minutes ago, but oh well.

CM
Sign in to follow this