January 2004 - Posts
Note: Stay tuned for pictures and GPS coords since I don't have them yet.
Okay, so we managed to get a room for Monday night so we headed up a bit earlier than we expected. We weren't supposed to leave until late Tuesday night, but our friend got an extra day off work and when that happens you just HAVE to go a day early. This put us booking our reservation at 5 in the evening (very close to booking deadlines and we ended up in an accessible room reserved for disabled people on the first night, though we couldn't tell any difference between this room and the room we got the next night?). Packed and ready we headed out around 12 midnight. Now Leavenworth should be a little over a two hour drive, but we took the scenic route. Rather than taking 97 North off of I90 we kept going on some little road that ran parallel to I90, so we didn't know we were going the wrong direction (that is what you get for following women drivers ;-) We realized the blunder a ways down the road when the GPS device notified us we were going in the wrong direction.
So we flash our lights about twenty times or so, and the girls just think we are going over bumps or something, because they keep going. We slow down, they slow down until we get back into range and then they start going again. They just don't get it that we are trying to get them to stop. We do this for a couple of miles and finally they stop because they think we have a problem with the Jeep, not because they actually realized we wanted them to stop. Again, they JUST DON'T GET IT! Because we are now of course they agree to let us drive. Being as we are almost at the point where I90 switches north we continue down this road rather than turning around and we take the scenic route to Leavenworth that puts us by Rock Island and through Wenatchee (yep we did a big fricken circle).
So we get into Leavenworth at 4 am, completely tired, and we have to get up by 11 to check out and check back in to our new room. Of course the two year old in the room above us doesn't realize this, but I can't fault the child (so I'm really pissed at any parents that might have had a two year old running around on a second floor room at Leavenworth, please contact me so you can give me back my 4 hours of wasted sleep).
Tuesday is a pure shopping day, since it was the bonus day. Of course I would have rathered that we climb that day as well, but it just didn't happen. Leavenworth is an extremely well built little Bavarian style town. They had all of the lights up still which made for a nice stroll closer to night. In the middle of town is a little sledding hill. The place is just cool to stay at. However, they lack good food. Our food experiences consisted of De Waffle Haus (very poor service, they don't know what a vegetarian burger should taste like, and I'm still wondering where my refill on the water is) and some chinese restaurant in the indoor mall (the food was okay albeit a bit overpriced, the owner was extremely/overly informative, but you get all the rice you can eat). The rest of the time we just made food in our room since we had a full kitchen in our resort (very nice).
With a full kitchen you can make just about anything. We went for a lasagna on Tuesday night which turned out very good. Large enough to feed us for two nights as well, even though we ate the remainder for breakfast on Thursday morning in the realization all the food needed to go before we left. Wound up eating lots of eggs on the trip as well, and of course I had to have my Cinnamon Crunchers cereal.
So did we actually climb? Yep, the girls wussed out and thought it was too snowy to climb, so we went on Wednesday and drove around picking out spots to hit. We spent about an hour at Fridge Rock, a small boulder with up to V5 problems. It was nice getting my hands on some real rock, it is actually much easier to hold onto than gym holds because of the sharper/varied texture. We took a bunch of pictures on this boulder and got some GPS coords which I'll throw up eventually. It took us forever to find this place because the locality of the maps we were using wasn't uniform (1 inch might be a mile, and the next inch might be 20 feet). After Fridge, we tried for several more boulders but realized in the snow, we weren't going to be able to get to any of them since most are 100 feet or so off the roads edge. We did manage to get to the Torture Chamber (took us 10 minutes of hiking in 3 foot deep snow), but we didn't climb much. Just admiring the scope of this set of rocks was enough for me. Torture Chamber is about 10 or 15 large boulders that are all next to each other, falling over one another, making for a nice cave, some good overhanging problems, some really nice crack problems, in short we are going back in the summer. We got coords for this rock as well as about 20 others, some of which weren't marked on the boulder guide, so they might be unknowns.
After our climbing experience we got back to the room and figured on doing some sledding. The resort we stayed at featured a HUGE sledding hill on which people were only going about half way up before heading back down. We couldn't figure out why nobody was going from the top, but we quickly learned first hand. By the bottom you are going about 30 mph or more (we should have clocked it with the GPS), and there are two bumps that shoot you about 6-8 feet in the air. Being extremely crazy, we did this multiple times, got some badly scraped up knuckles and some sore bums, but it was a lot of fun. Realizing it was slow going down one at a time and walking back up we grabbed a community sled and took it up. Note that nobody said anything when we grabbed this sled. So we head down, my friend breaks the sled, and some little girl starts crying because we broke her sled. (This is an oh $hit moment coming I'm thinking). So we offer to pay for the sled, no go, we offer to give her our sled, no go (her's was cooler after all). This puts us in a dilemma. We head back to the room, grab the wallets, and head back to the family so we can talk with the parents. Of course the parents thought we were running away, we quickly advised them we weren't, we were sorry and what not for destroying the sled, and how fun the ride was ;-) All is good, and everyone is happy again!
Thursday actually puts us all at the breaking point of tired. Had a hard time sleeping the entire trip so we decide not to hit any more natural rock (especially after only finding two good boulders the first day that were usable in the snow). We just headed back, got in around 3'ish and took a nice nap. Woke up long enough to eat, and then hit the sack for the night.
I enjoyed the trip quite a bit. Plan on seeing more travel journals like this one in the future.
Well, one of the features of the places that I stay when on vacation is that they don't have any sort of ethernet hook-ups in the rooms. They still have a small datacenter, but not something you would really want to connect to the internet with given the non-existent security on shared terminals. I have to say, it wasn't my idea to sign up for such a vacation service, since my primary question when normally getting a hotel room is whether or not the place has a free DSL hook-up in each room. I simply can't live without it. However, I gave into the whims of Worldmark (maybe some of you guys are members) and so now I get an unlimited number of vacations each year for extremely cheap prices.
That said, I'm off to Leavenworth to do some outdoor climbing. It probably isn't the best season for it, but I have a couple of weeks before my contracts really start up, so I'm taking 3 days to hit some rock. If you follow my normal blog feed you'll find that I'm not a great climber yet, but I'm really getting into it for sport. Mainly bouldering, but I might actually attach a rope this time around and try out a pitch. I'm going with an excellent climber, primarily a boulderer as well, but I'm told he is somewhat versed in the art of lead climbing. It'll be an exercise in trust since I've never had to support anyone on lead climb.
Well, I'll try to log in and post on my blog over the next few days from coffee shops, and other places with free hacker infested Wi-Fi ;-)
If you take a look at KB article 320348 you might think it was the holy grail if you were trying to figure out how to compare binary files using the .NET Framework. However, the code isn't really written all that well and to the less astute programmer, it might go straight into production use without so much as a code change to make sure the routine worked properly. So what am I worried about from this function?
1. Not checking the null string case. You really shouldn't pass a null string into a FileStream. Just not good coding practice.
2. Not checking for file existence before creating the FileStreams. “Try“ing for exceptional programming they are (without the try).
3. Not putting the FileStream's into a using statement or something that protects their closure if something goes wrong:
(for instance, if FileStream1 exists and FileStream2 throws an exception FileStream1 stays open a while.)
I can live with the rest of the code, it doesn't seem all that bad. But the question remains. Should KB articles that attempt to create non-existent technology do so with the mindset of LCS (least cost solution) or should they adopt a best practices approach? Should the code be usable out of the box, or should it simply be a technology sample that needs to be cleansed by the proper authorities before being used in an actual application? I welcome any comments, negative or positive, since I'm really curious what other people think.
http://support.microsoft.com/default.aspx?scid=kb;EN-US;320348
For those that have seen me around the gym, it was time to get some new shoes. Being a new climber I quickly blue out the toe on my La Sportiva Mythos. Most likely the blowout was from inferior toeing on texture, and even more likely from jumping off the top of the wall with that No Fear attitude that gets new climbers into so much trouble.
I have to say that I'm not going to stop jumping from the top of the wall. It is quite a bit of fun, and often the only way to get down off of difficult problems. I also love to dyno and you more often than not end up landing in gravel than snagging your target hold (especially on the really good dynos). So I went with the Mad Rock shoes this time. They are quite a bit cheaper than the Mythos that I got before (nearly half the price), and I have to say they have a much better edge.
Mythos tend to be a good all-around shoe allowing the wearer extended usage periods without foot fatigue. Great for climbing endurance routes or multi-pitch since I've been in my Mythos for over 5 hours without having to take them off. They have some soft rubber so your foot can really feel the underlying rock, but the soft rubber is what burst so quickly. They were also inferior at holding onto an edge, at least on the feet of a new climber.
The Mad Rock Mugens are a bit better. They offer an extremely comfortable and tight fit with only the slightest amount of foot pain (foot pain is good). They don't have too much of a banana curve, so they don't give your feet the arch that enables you to do better on overhanging walls, but tends to force you off of more vertical routes where toe friction is really important and you can't get your full toe onto the wall because of the extreme banana like foot angle. They are also velcro, so you don't have to lace up and delace as you are moving from climbing area to climbing area. If your feet do start to hurt you can quickly take them off.
I got a chance to try my new Mugens over at the REI wall in Redmond. Not a very fun wall I have to say, but there is a nice hidden edge on the back side next to the outside windows. A good friend of mine working over at REI pointed it out, Michael Johnson, while I was trying on various pairs of shoes, and I have to say I'm very glad he did. Otherwise I would have been stuck testing shoes on lame texture, and I probably would have picked a different pair based on performance on those other surfaces. I need to break these guys in before Wednesday and Squamish, so I'll be at V-World tomorrow (today, Sunday), and probably Monday as well.
So I took the time to write some code today to process a flat file. The flat file didn't have too many rows, only about 1800, so I figured the routines would run farely fast. They did, at about 65 milliseconds on average parsing a CSV file with 8 or so fields into a strongly typed data structure, and then placing said structures into an array list.
I did some neat things with the structures, like making them sortable on any field in any direction, etc... But that wasn't the part that was hanging me up. I thought the darn code should be running a bit faster. Since the code is a basic string.Split, a couple of int, bool parses, and a datetime parse along with the object construction I figured the problem had to be in the parse routines. Now, I know that integer parses can't be that darn slow, so I left those in. I did, however, take out the datetime.Parse. to my surprise the speed came down to 23 milliseconds or less. I basically got a 200% performance increase by removing a single datetime.Parse line. I realize that parsing dates must be a fairly hard task, but I would think if the exact structure of the date is know, the parser could be very fast and very determinate.
Well, just figured I'd point out to beware of any DateTime fields since they tend to be slow in the parsing area. Maybe someone from the BCL team can comment on how to make better use of it. I did try taking some examples from the DateTime best practices guide and pass in a custom ParseExact format. It did get a little bit faster, and actually dropped me down to an average run time of 41 ms, so I guess I have to say it got a LOT faster than it was previously. I'm still thinking a custom formatter class run over top of the string might yield an even faster result because of the complex code used by the DateTime class in order to switch to specialized methods based on my custom parsing format. After all, DateTime is really a swiss army knife when all I really need is a sharp stick to poke someone in the eye with.
A friend of mine is getting into game programming. He is actually heading back to college and taking the necessary classes to break into the field. Since the first few semesters will be kind of bogus in terms of actual game development stuff I'm working with him on some various projects so that when he gets to the harder courses he is ready for them.
He kept mentioning that he had worked on a basic tic-tac-toe game in Visual Studio. I think everyone tries this out at some point. Almost like a challenge I'd say, “How fast can I code Tic-Tac-Toe!”. But I think everyone else that sits down to this task has a different goal than I do. When I sit down to a new game I think about the game engine design principles and how I can apply them to tic-tac-toe. Who cares how fast I plug it out, or even how pretty it is, IMO, but instead would you use the same principles in a larger commercial style game.
So I went over his Tic-Tac-Toe game (don't kill me for posting about this here John, others can learn by your example ;-) and he had taken the how fast approach. Then in the same email he had a large list of feature enhancements he wanted to work on. Basically things he couldn't do during the initial phase of development and so he wanted to figure each of them out in turn. The problem was, because of the initial engine design, everything he does is going to be a bolt-on, rather than an extension of the engine. He never separated his presentation layer from his input layer, or his input layer from his game engine layer, etc... Basic principles, that when in the game development field, you try almost always to follow (and when you don't you wind up as a post-mortem in Game Developer Magazine). So here is the contents of the mail I sent back since I think it might get people's thought processes going about how to organize code (even non game type code) to make it more extensible.
I'll run through some stuff for you. Basically what I need to point out is that Tic-Tac-Toe as a game really only has a single engine. I'll run through some basic concepts to define what a game engine is and how it works:
Fact: A game engine consists of a game state, methods to change that game state, and methods to report that game state.
Fact: A game engine should be independent of user input methods, display, and any other connection that doesn't have to do with a game state or the methods needed to change the state.
Fact: A game engine has a lifecycle that consists of setup, iteration, and conclusion.
So think of a tic-tac-toe engine (make it a class) that is independent of the UI (have the UI interact with the engine by using it to make moves and then displaying the results of those moves rather than allowing the UI to actually take part in storing the game state) and the user input (don't have the buttons pressed set game state directly, instead have them call methods on the engine that change game state in a protected manner).
So a tic-tac-toe game might have the following game engine layout:
Setup
Clear Game State
Select Piece that Moves First (X or O)
Iteration
If GameOver Throw Exception
Make Move by turning a click in the UI into a game engine method MakeMove(cellX, cellY, PiecesEnumeration.O)
If cellX or cellY is taken or PiecesEnumeration doesn't mesh with the current move piece Throw Exception
Else SetStateOfBoard
CheckForWinConditions
If WinConditions SetEndGameState Goto Conclusion
Else CheckForDrawConditions
SetEndGameState Goto Conclusion
Conclusion
ServeResults
So out of the things you wanted to add to your game. Most of them were UI items, not game engine items, but you don't actually have a game engine yet. Lets finalize a game engine, something cool that works well that can be played from a command line, a winforms UI, or a web page with relative ease. Thats the key to an awesome game design.
So what you should send me is:
a) A single class that I can compile into a library
b) I can link that library into a new application I'm writing and add the ability to play tic-tac-toe
Well, I went ahead and burned another three hours at vertical world today. Could argue that it was a waste of time, since I wasn't able to hit anything very hard, but I did manage to get my muscles stretched out, relaxed, and into the groove of things. Bunch of new routes went up today at the Redmond gym. A new V5 set up by Teego that shows all of it's V5'ness within the first move consisting of a really tough foot and hand match right off the start hold.
There was also some new overhanging routes set up by Brian. Maybe not new, but new to me since I hadn't seen them the previous day. The route in question was a nice V1+ Power route. A power route is generally coined when your footwork and balance aren't going to play a huge role in sending the problem. This route definitely required a lot of power with 80%+ of your body weight being supported by your arms at all times.
I saw my first VH today. I'm assuming this is what you would call a V-Hard. Hard enough that Jarrod Vsui and Joel couldn't hit the route in order to rate it. Or maybe they did and would just rather leave up a problem without a definite rating so some of the better climbers would still try it out. Believe it or not, some of the V12 capable climbers in the gym shy away from the chance to send a V10/11 or better problem because of the insane amount of dedication required to finally send it. Most V10+'s take at least a few days of work in order for even the best climbers to send from what I've been told.
I'll have to keep everyone up-to-date on new routes at the Redmond gym. The boulder route setters have been setting almost a route a day on average so there is always cool stuff to climb. Just today 3 old routes came down in favor of putting up a couple of new routes, so the holds are starting to be recycled again and stagnant routes are being removed. For anyone really working a particular route this always spells inevitable doom, since you might lose your chance forever.
As more and more places are setting up free wi-fi access points to bring in business, more and more people are grabbing wi-fi cards for their laptops and palm devices. Personally, I think the freedom of being able to freely connect to the Internet from the sidewalk very interesting, and I'm definitely enjoying the anonymity of surfing on a system that doesn't track my existence.
But what about modern day hackers, what kinds of benefits are they deriving from this? Well, in the 90's a lot of money was spent on protecting you via hardware and via tracing design patterns. Pretty much every ISP you work with now will give out your home information to the FBI in a second if requested due to you hacking someone over in Europe. There is simply too much of a paper trail with any home connection that you might achieve, even if you use the age old process of tunnelling through multiple intranet clouds, assuming you've already gained access to any. This means physically, you've been nailed down to a physical existence somewhere on earth, something that scares most virtual netphiles to death since they no longer have the privacy of logging off and removing themselves from *dangerous* situations.
Software firewalls are getting pretty prominent in the market as more people disconnect.and find they need more protection than the OS provides (or simply feel better with the increased security). Heck, Costco sells stacks of the new Norton Firewall, and they go through those stacks very quickly each day as people scramble to protect themselves. Hackers have been whacking hardware firewalls for years though, including those protecting some of the most advanced systems on the Internet. Systems where the design is kept so secret that only gentle black box probing is going to get them any information as to where the access points might be. With software they get the added benefit of spending 50 bucks and using a disassembler to learn the secrets of the program, a treasure trove of information on how to get through.
So what am I saying? Wi-fi access points are becoming a haven for hackers. They gain back all of the edge they had before the big push for security. The get anonymity, they get it for free (AOL used to do this for the inititated ;-), they generally get a decent connection, and they get to walk away when things get hot. Most importantly, they regain the ability to slowly probe systems over time, taking small steps, rather than the recent change where hacks need to be planned for months on end.
Note: This article does not apply to all the CSS hackers and script kiddies out there that don't know how to use a disassembler, cause a buffer overrun, or raise their security privs when logged in using a normal guest account. You guys are only prominent in news feeds because of click happy email freaks.
While helping someone with a DirectX problem I came across what I think might be a neat feature for Windows Forms. You can always gamma correct your UI to a lower brightness value by layering a transparent black from over the top. This as mentioned in the title is useful for telling the user the application is in a sleep state, and it means that you can control how they interact with the application when they come back (by say, making them click the transparent form). So what exactly am I saying? Well, first off create a new blank form without any borders or titles and attach a MouseUp handler so you can dismiss the form later.
this.FormBorderStyle = FormBorderStyle.None;
this.Text = "";
this.MinimizeBox = false;
this.MaximizeBox = false;
this.ControlBox = false;
this.BackColor = Color.Black;
this.TopMost = true;
this.ShowInTaskbar = false;
this.MouseUp += new MouseEventHandler(this.Form_MouseUp);
this.VisibleChanged += new EventHandler(this.Form_VisibleChanged);
Then you are going to want to set the opacity of the form to some value, like 20%. This darken the the controls on your form considerably.
this.Opacity = 0.2f;
Finally, you'll need to show this form using ShowDialog(this) from within the parent form. You might also set the Owner property to the current form, so you can set up your transparent dialog in the proper location. You may not actually need this, but do it just in case. If the main form is minimized, it will also minimize the owned form (dialog), so I think that is pretty cool.
GammaForm gammaForm = new GammaForm();
gammaForm.Owner = this;
gammaForm.ShowDialog(this);
Finally, you'll work through those events. The mouse event needs to close the gammaForm, and the VisibleChanged should position the gamma form over top of the parent.
private void Form_MouseUp(object sender, MouseEventArgs e) {
if ( (e.Button & MouseButtons.Left) == MouseButtons.Left ) {
this.Close();
}
}
private void Form_VisibleChanged(object sender, EventArgs e) {
if ( this.Visible ) {
this.Location = this.Owner.Location;
this.Size = this.Owner.Size;
}
}
Wooh, rest assured the code is functional, I just went ahead and used it. In order for the minimize to still work though, you'll need to use the Show() method instead of ShowDialog(this). The reason here is that when a dialog is shown you can't really interact with the main form's control features in the task bar. I'm sure some Windows APIs or spy utils could probably do it, but that doesn't count.
I have definitely wanted to get access to the gradient title colors a number of times. I'm sure some people have gone out and written their own calls to get these, but others I'm betting haven't. Out of all system colors, only two don't show up in the KnownColors and therefore SystemColors areas of System.Drawing. These happen to be GradientActiveCaption and GradientInactiveCaption. I'm including some source below that grabs colors just for these two items. You could probably do some work and have them automatically create linear gradient brushes too, but I'm not going to do all of the work for yah.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
public class SystemGradientColors {
[DllImport("user32.dll")]
private static extern int GetSysColor(int nIndex);
// Constants for gradient colors
private const int COLOR_GRADIENTACTIVECAPTION = 27;
private const int COLOR_GRADIENTINACTIVECAPTION = 28;
private static Color colorGradientActiveCaption = Color.Empty;
private static Color colorGradientInactiveCaption = Color.Empty;
public static Color GradientActiveCaption {
get {
if ( colorGradientActiveCaption == Color.Empty ) {
int color = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
colorGradientActiveCaption = FromWin32Value(color);
}
return colorGradientActiveCaption;
}
}
public static Color GradientInactiveCaption {
get {
if ( colorGradientInactiveCaption == Color.Empty ) {
int color = GetSysColor(COLOR_GRADIENTINACTIVECAPTION);
colorGradientInactiveCaption = FromWin32Value(color);
}
return colorGradientInactiveCaption;
}
}
private static Color FromWin32Value(int value) {
return Color.FromArgb(value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF);
}
}
More Posts
Next page »