A Story
Jun 10, 2011
It all started when we were going to one of my friend’s graduations. Though, maybe that’s a bit misleading; we didn’t go to the graduation, we went to the end of it, because my mom’s work servers’ air-con went wacky, and she had to stay an hour late and fix the things. You know how it is.
Anyway, we met my friend’s father, a family friend of ours. I always figured he and my dad were childhood friends, or something of the sort. After I got the car parked, he gestured to us and told us - in Chinese - “I’m going to go find Mo (my friend). Wait here!” So, we waited at the sidewalk, next to all the fathers and mothers, the sisters and the brothers, and the graduates in red and white - the colors of Bloomsburg High School. We waited awkwardly for twenty minutes; a graduation of a class of 99% white students is no place for a Chinese family. But, we waited anyway, as was our obligation.
Eventually, after the hat-throwing, Mo did finally make it out of the crowd. He was dressed in a red graduation gown. “Hey, Ed!” I stuck out my hand to shake, but he had nothing of that and went around my back with one hand. “How’s it going?”
“Pretty well, thanks. Congratulations!” I handed him the package and bag my mother had prepared for him, but he gave it to his father. He said, “I’ll be right back!” and left to find his classmates.
I stood around for another half hour while my parents, his parents and other Chinese well-wishers made small talk in Chinese. All the while, I did what adolescent boys are wont to do when left with no tasks; I looked at girls.
I could say I’m a hard guy to please. I could say that none of the girls caught my eye. But that’s not really true. I might have taken any of them if they were so bold as to walk up to me and just say “Hey.” I think this is secretly every guy’s dream; that they are good enough to simply approach in a crowd. But I know this is not really true, from my years of experience, and so, at every gathering, I wait for that girl, a girl, any girl, to just come up and say hi.
But it never happens.
Afterward, when Mo was done congratulating and hugging and taking pictures with all of his classmates, our families, along with another lonely Chinese professor came to congratulate Mo, all went to a Japanese restaurant called Arirang. Yeah, I know the place is called “Oliran” now, but Arirang was so much better. It has much more of a ring in its name, to me, at least. Arirang is a Japenese Hibachi restaurant, which is really a contradiction, as Japanese don’t do Hibachi, the Koreans do. Anyway, there were Chinese symbols on the shades in the window, and this put us at rest.
Arirang is the type of foreign restaurant which relies on American culture to thrive. They serve Japanese/Korean/Chinese cuisine, but that’s where the foreign-ness ends. The Hibachi chefs are really just there for show. Sure they know how to grill on the iron Hibachi stations, but really what makes them money is showing off and pleasing the crowd. They always start with a bout of flipping forks and knives around on the grill like a drum player twirling sticks. Then, they lather the grill with oil and set it on fire, putting fear into the more skittish of the crowd. Afterward, they start the cooking, but even this is a show. As they cook, they shout to random people, “Open up!” and flip a piece of zucchini or melon at a waiting mouth. They follow this up with a squirt, or sometimes a long stream, of sake (Japanese wine) all the while stirring their audience into a chant of “Go, go, go, go!”
By comparison, the food is merely an afterthought. It contains all the traditional staples of Asian food; a side of noodles or fried rice topped with meat or vegetables of your choice. It is extremely salty, and tastes of garlic and soy sauce. Not much else can be said for it. It is not for the food that people come to Arirang, but for the experience.
Interestingly, our Hibachi chef spoke Chinese. There is something to be said for a common native language; our table felt somehow warmer, more comfortable than other tables where the chefs were shouting, “COME ON BABY! OPEN YOUR MOUTH! I KNOW YOU CAN DO IT!” with strong eastern Asian accents. In contrast, while our table still had the food flinging and sake squirting, we were more laid back. The shift manager came to spoke to us, also in Chinese. He seemed a very lonely man. He came by twice, but he did not talk to any of the American customers, only to us. However, he was very kind and gentle, even going as far as bringing out a fried ice cream - a bit incongruous in the Asian-themed restaurant, but the thought was there - for Mo to congratulate him for graduating, on the house. After our chef left, we talked among ourselves about things of little consequence: my return to college to take summer classes, Mo’s visit to China beginning the next day, his parents moving back to China after their stay of two years for their son’s sake. It was all very relaxed, but it was a nice farewell. We passed away two hours like this.
Of course, I had to drive back because both my parents had two beers. On the way, my mother lost some of the calm and said, “Finally, finally they are going back. I can’t take all these obligations.”
“Surely you wouldn’t regret helping out a childhood friend of dad’s?” I asked curiously.
My mother snorted. “A childhood friend? Mo’s father is a man your father met on the plane to China.”
I blinked, suprised. I looked at my father, and he nodded in confirmation.
We rode in silence for the rest of the trip, and I reflected on the nature of friendship, and common language, and food flinging and sake squirting and all these things. After we were back home, I sat down and wrote this. Excuse me if it’s a little rough around the edges, it’s 11 PM and I’m a bit tired. Good night.
The Kingkiller Chronicle
Jun 7, 2011
“‘You can divide infinity an infinite number of times, and the resulting pieces will still be infinitely large,’ Uresh said in his odd Lenatti accent. ‘But if you divide a non-infinite number an infinite number of times the resulting pieces are non-infinitely small. Since they are non-infinitely small, but there are an infinite number of them, if you add them back together, their sum is infinite. This implies any number is, in fact, infinite.’
‘Wow,’ Elodin said after a long pause. He leveled a serious finger at the Lenatti man. ‘Uresh. Your next assignment is to have sex. If you do not know how to do this, see me after class.’”
- The Wise Man’s Fear, Patrick Rothfuss
Great humor is just one of the reasons I really love the Kingkiller Chronicle.
I don’t want to give anything away, like every blurb I’ve ever read about this book, so just be content to know that it’s a book about Kote, an innkeeper, who knows many stories, but tells just one over the course of a trilogy. As with many other books/games I’ve read/played and think are great, I don’t understand the complaints many readers give about this book, but hey, everything’s that way, right?
Double Album Lifdoff
Jun 1, 2011
I don’t know why I like the Homestuck music so much. There are definitely some songs that I don’t like, and some themes that are repeated a little too often (_doctor_COUGH) but the only other songs I’ve gotten into so much are the ones from the Cowboy Bebop OST.
Honestly, after hearing Bowman’s performance with “I Don’t Want to Miss a Thing” from Volume 6, I was not looking forward to his solo album, but it’s actually really great. I don’t like some of his random rises in pitch, and his voice isn’t perfect, but the songs within the album are high energy, and that’s what I like.
I don’t even have to talk about the other album. It’s Homestuck Volume 7. It’s good.
If you don’t know what Homestuck is, you must find out now. Not everyone likes it, but if you do, you will begin to obsess over it. You will look through every crack through which light shines, looking for meaning. You will look upon certain numbers with a new eye. You will swear to the eldritch broodfester gods that you will scrape every last secret from the surface of the runny [sopor] slime of webcomic that is MS Paint Adventures. And you will enjoy every minute of it.
Edit: And to reinforce my assertions, Homestuck Vol. 7 is #1 of bandcamp.com downloads today (June 1st 2011), with MTaHK at #2.
Frozen Synapse Review
May 29, 2011
This game is pretty awesome. Been playing it with my brother the last couple of days and it really takes some strategy and pre-planning.
Frozen Synapse is very hard to put in a genre. At first, if you watch the trailers, you’ll assume it’s some kind of squad-based top-down shooter. In fact, it’s anything but. It’s a tactical turn-based strategy game that is comparable to chess. You start out with some number of units, usually 3 or 4, and you can give them orders on what to do the next turn. Each turn is 5 seconds; this is a fairly arbitrary time, because it all really depends on how fast your units/grenades/rockets move. Games are on average 30 seconds in game-time, but they can take 20 minutes to play out. I know that sounds like a contradiction, but imagine watching a chess game live, with the players thinking about their next move after every turn, versus simply watching all the moves after the fact without any player deliberation.
The grenadier in the top left being shot at ends up surviving, because of his position behind cover
The game is all about positioning and foresight. If you predict that a grenade might be coming at you the next turn, you might duck behind cover. However, this might lose you an opportunity to gun down the incoming shotgun soldier. Or maybe not, because the shotgun soldier instead took cover as well, anticipating that you would not take cover. You might position all your units to defend a certain room, only to see that your opponent has predicted this and shot a rocket at the room (which blasts down walls). The possibilities for gameplay are endless. To win in Frozen Synapse, you must predict well and sometimes take some risks. For example, shotgun soldiers shoot much faster than any other type; however, their capabilities are limited by their range. Often, you can take down enemies by simply rushing your shotgunners into them, but it’s risky because you never know what the enemy is going to do. Your target could simply back up and another of your enemy’s soldiers could come in and shoot your shotgunnner from behind.
Frozen Synapse does have a slight element of chance; either one of two machine gunners firing at each other down a long hallway could get shot before the other does. However, this element of chance is largely removed by the ability to run simulations. Not only can you control your soldiers, you can control the enemy soldiers in simulations to attempt to predict how the enemy will move and react accordingly. When you don’t know if your shotgunner will be able to take down the enemy machine gunner before that sniper over there gets his shot off, you can test it out and see what happens. This, I think, is the greatest feature of the game because it could have been a game of chance - and thus, frustration - without it. It doesn’t make the game imbalanced, either, because the enemy won’t always do what you predicted in the simulation; he could have second-guessed you, predicting what you predicted would happen, and taking a different, superior route. Again, it’s all about positioning and foresight.
An interesting option on each of the game modes (There are five of them, but I’ve only played extermination, in which the goal is to eliminate all of the enemy’s units) is the option to turn the arena “dark.” When you set this flag, you cannot see where the enemy units are unless you have a clear line of sight. It introduces a new element into the mix, but I prefer the “light” option, because with “dark” on, you cannot run simulations with enemy units, thus introducing that element of chance.
I have only a two gripes with the game. The first is that when I bought it on Steam, the servers were very, very slow. It would take minutes to log in. It’s fixed now, but there was a tradeoff; they have split the multiplayer game into many servers. You can only challenge people that are on the server you are currently on, and the servers only have about 50 people on them at a given time. However, it’s the lesser of two evils.
The other gripe is one of balance. The game randomly generates levels and, often, randomly places units. Many times, this results in unbalanced positioning; a shotgunner may be placed right outside a room which contains an enemy grenadier, ensuring the grenadier’s instant death. Other times, one player’s units may be spawned in a room with only one exit, and all it takes is a single rocket from the opposing player to kill 2 or 3 out of the 4 total soldiers. There is a “symmetric” option when generating maps; however, I find this makes games somewhat static. There isn’t really an easy way to fix this. One suggestion I do have to remedy this flaw is to allow soldiers to jump over cover, thus eliminating some chokepoints. Of course, this maneuver would probably take one or two seconds (a long time in game-time) to execute.
tl;dr, Frozen Synapse is a terrific game that you should definitely try. For the price of $20 for two copies of the game, it’s worth it. It has great visuals and gameplay different from any current genres. It won’t appeal to everyone, but it’s definitely worth a shot.
Here’s a video of a game I played with my brother, after the fact (no deliberation between turns)
I’ll post one of me playing a match live, later.
Visual Studio Backups, Profiling, etc
May 22, 2011
Wow was I in for a scare when I got back home today. For my independent study at Penn State, my professor wants me to speed up this “Sonoluminescence” program that a guy at UCLA wrote for his dissertation. He wanted me to use a program profiler. I found out that Visual Studio’s profiler was only available in the Premium and Ultimate editions - I can only get Professional through the MSDNAA program at school. I found out that Netbeans has a profiler for C++, so I downloaded it and tried it out on my current project (JAGS). Well, I found out two things:
-
The Netbeans C++ profiler only works on Solaris/Linux. (The Java profiler works on Windows, though, for what it’s worth.)
-
Back up your freaking files, because you never know when you will accidentally move them instead of copying them, delete them because you thought you’d copied them, and then uninstall some massive program, making file recovery programs useless.
I was in a panic for a while. I tried out three different programs before realizing I had barely changed the very error-prone version of my program (read my last post) after I’d copied it into a new solution. It turned out I basically had backed up the entire thing. If that error hadn’t popped up, forcing me to create a new solution, instead of wasting a day in frustration I would have lost my entire project.
Irony, anyone?
As for the profiler, I downloaded a nice program made by AMD called AMD CodeAnalyst. Actually, that’s what made me realize my project was gone, because it couldn’t find any source code. I am also trying out a profiler called “Very Sleepy.” I’ll post back on which one is better next.
On backups, I looked around and couldn’t find anything that was automatic except for SVN/Source control, which I don’t want to have to set up right now. Thanks to this blog post, I’ve discovered DPack, which includes a nice manual backup utility. It does other things too, but I don’t know what. It zips your project for you and everything; I just have to remember to hit a button every so often, and thanks to this experience, I will. My project in zipped form is only 54kb. Nice.
In-compiler vs Release Builds
May 21, 2011
I ran into a very strange problem yesterday. My program had an error in it that appeared only when I ran the exe from the project release folder, and not when I ran without debugging (or with debugging) in-compiler. It wasn’t a terrible, terrible problem; my program still ran. It was just that every so often, when a player fired a projectile, the projectile would be assigned the ID number 1952870259. This exact number, every time. However, it was a very peculiar problem, in that even when running a debug version of the exe from folder, the problem did not manifest. That meant I couldn’t debug the solution using Visual Studio, and that didn’t go over well with me. I went over and over my project properties to no avail, even creating a new project within the same solution, copying over all files from the server into the new project and not importing any project settings. The problem was still there.
Of course, at this point I concluded it had to be a problem in my code; I’d created a new project and copied over all the files. The only variable left was my code. So, I began debugging without the debugger, and eventually I came to the conclusion (hours later) that the problem only occured when a projectile hit a wall. No big deal. I went to that block of code, and I found… Nothing.
Argh.
At this point, I was frustrated beyond belief by this and other problems occurring in my life, so I took a break and played some Heroes of Newerth with friends. Won some, lost some, I’m sure you know how it is. Today, I went back and copied all code to a new solution and ran the program in debug mode just to make sure it compiled. After fixing some problems I forgot were inherent in starting a new project with Dark GDK, I ran the program, shot a projectile at a wall and BLAM, runtime error.
W T F. This didn’t happen in my other solution. I went through and fixed the error. It was very simple, a list iterator was going out of bounds and pointing to nothing; thus, the ID that was being assigned to the projectiles was some random number gotten by the program from null memory. But that still didn’t answer the question of WHY. Why did my program only throw the runtime error when I had created a new solution? Who the hell cares, right? I’d gotten my program to work. But this experience just goes to show how reliant I am on the Visual Studio debugger.
Collision Detection
May 16, 2011
I put working on the master server on hold for now, since I figure Collision Detection is a more important problem. However, I’m running into problems with it; I’m trying to do it serverside, and while I do run into walls, they are invisible. Invisible is the wrong word, I suppose; the server is doing what it’s supposed to, but I think it’s a problem with what you see vs what the server has in its room coordinate/dimension arrays. For example, when I was doing respawning, it kept putting me in random spots instead of inside the rooms. I figured out that it was because when passing the room coordinates clientside, you needed to pass “32 - y coordinate of the room” because of the switched coordinate axes of 2D drawing (down is positive in the y direction). I’ll figure out what it is eventually.
In other news, I have recovered from a week-long throat infection. Not that anybody follows this blog anyway. Also, my independent study with Dr. Fomitchev at Penn State is kicking off. I’ve got a 100-page dissertation from UCLA to read, and a program to attempt to understand. Awesome.
Master server with MySQL
May 5, 2011
I’ve been wondering over ways that I could build a master server. If you don’t know what a master server is, it’s a server that contains a list of servers that other servers poll to get the server list read that five times fast. What with me being a poor college student and not being able to afford to pay for an actual dedicated server, I came up with an idea; use a database to store server names.
I’ve had very minimal experience with MySQL, but I know that it is a database and it can store things in tables. Hostable, the very nice (and free) hosting service I’m using to run this website, offers free MySQL databases, so the price tag at least is taken care of; the only question that remains is: is it possible? The only MySQL application I’ve ever written was a little signup for a WoW private server I ran for about two weeks and then retired (for more lack of dedication, see BookReaderHD). I’m wondering if it’s even possible to use C++ and MySQL together like this. I did a bit of research (read: searching on google) but I found nothing; I guess I’ll just have to find out myself.
There’s voice in my head that says “Collision is the real problem you have to fix;” be quiet, I’ll get there, ok?
Asynchronous Input in Dark GDK
May 4, 2011
For a while I was puzzled as to how to get input asynchronously in Dark GDK - that is, without interrupting the regular flow of things, mostly drawing functions. It turns out there is a function for that, dbGetInput(). By the way, DarkGDK’s documentation isn’t the greatest - dbGetInput is listed as dbInput$ in the docs.
Anyway, as soon as I used it, I ran into another problem; dbGetInput didn’t support backspace. After a bit of poking around on the forums, it turns out you need to do that manually. Someone on the forums made a little function to do just that, which I modified to support multisync and C++ strings. Here it is:
//Function to get input asychronously; returns true if input is still being fed, false if the input has been sent to the server
//Credit goes here: http://forum.thegamecreators.com/?m=forum_view&t=160546&b=22
bool GetInput(std::string& Buffer, int MaxChars)
{
std::string NewEntry = dbGetEntry();
// dbGetEntry returns zero before the first character is typed.
if (NewEntry.length() > 0)
{
// Afterwards, the returned pointer is not zero but the string can be empty.
if (NewEntry[0] != 0)
{
dbClearEntryBuffer();
// There can be more than one characters in the returned string
// if the user types fast. Add the characters one by one.
int NewLength = NewEntry.length();
for (int i = 0; i < NewLength; i++)
{
// Backspace: remove the last character from the string
// if there is still any left.
if (NewEntry[i] == 8 && !Buffer.empty())
Buffer.pop_back();
// Enter: Send the message to the server if there is a message.
else if (dbReturnKey())
{
if(!Buffer.empty())
{
//Send the message to the server so it can distribute the message
NetPutString("PlayerMessage");
NetPutString((char*)Buffer.c_str());
NetSend(0);
}member
return false;
}
// Otherwise: add the character if the buffer is not full yet.
else if (Buffer.size() < MaxChars - 1)
Buffer.push_back(NewEntry[i]);
}
}
}
return true;
}
Here’s the function in use:
// ============ TYPING HANDLING =============
//If the player presses T, start the typing prompt
if(dbKeyState(DIK_T) || typing)
{
//The player is now typing, set the typing flag to true
if(!typing)
{
dbClearEntryBuffer();
chatBuffer.clear();
typing = true;
}
//Get the input asynchrounously
if(!GetInput(chatBuffer, CHATBUFFER_MAX_SIZE))
typing = false;
dbText(0, dbScreenHeight() - dbTextHeight("a"), "> ");
dbText(dbTextWidth(" > "), dbScreenHeight() - dbTextHeight("a"), (char*)chatBuffer.c_str());
}
Edit: Made the code a little cleaner, using strings more.