Matthew Leverton's Blog
-
Everything is a go!
The rules have been loaded. The only thing left to do is wait!
I've got to see if I can remember how to use Allegro. Below you'll see where the greatest game will be made. -
It Has Begun
SpeedHack 2005 is officially underway. I believe the rules are pretty clear, but if you have questions ask here or on IRC (freenode) #speedhack.
-
Rebels and Lords
I went through my stack of C64 magazines looking for a game. Considering the "classic" rule applies to all C64 games and I should be able to fit any game to the genre, I focused on Dichotomy and Randomness.
I ran across a strategy game called "Rebels and Lords." What more can I ask for? I've got Dichotomy right there in the title. Attached is an example of the type of graphics you can expect. -
Game Setup Screen
Yes, I'm going all out with the interface.
prompt(buffer, response, 3, 0,16, makecol(255,255,255), -1, "HOW MANY CASTLES?");Now, I just need to make that a prompt_int() function, and I'll be all ready to work on the game itself.
-
Maps Ahoy!
To comply with randomness, all maps will be generated randomly. Also, there will be a huge element of chance in the gameplay. So, this will be one of those chance/strategy games.
There are three basic map types:- Plains - No mountains or trees
- Forests - Lots of trees grouped together
- Mixed - some trees and open space
Both the forests and mixed types have a mountain range down the middle.
-
Rent Me a Castle
I surfaced for air and food (double egg & cheese toasted sandwich and a banana), but now I am back.
I decided to put the bitmap sprites into the font, because that's how the original game worked. I've added castles, which are color coded based on who is in control. -
Better Castle Placement
Once and a while all the players would be starting very close to each other. Given the way the game works, that means you could easily be defeated on your first turn. So much for survival...
To compensate that, players have to start in one of the four corners. The position within the corner is random, so you could still start somewhat close to each other.
To be true to the original game, you are asked if you like the map. I think the original game did that because occasionally it would forget to give one of the players a castle... -
MATTHEW LOOKING
I've added the cursor. When looking at other people's castles and troops (not shown yet) you don't get to see them (the strength & numbers).
It also tells you if you are looking at rocks, woods, or grass—in case the art is too abstract for you to tell. -
Go to war
You can now divide up your troops into armies and send them out to battle. Well, almost. They don't actually go anywhere yet.
The three screenshots show the method of sending troops to battle. First, you have to find idle troops. Then you divide them up into armies and tell them where to go.
I'm going to take another break here, but I hope have the game finished by bedtime. -
Site Updates
There's a new page for viewing recents comments. If you're signed in (and competing) you'll see a second link to easily see comments directed at you.
Not that this has anything to do with my game, but I'm even more sick of looking at ugly green grass than you are. -
Moving right along
After a long break, I finally got myself to push a few more buttons. I needed to code the army movements. First, the armies didn't go anywhere.
I was setting the coordinates incorrectly:army->x = x;
army->y = y;
army->dx = x; // should have been sx and sy
army->dy = y; // for the "selector x / y coords"Of course, that was the last thing I checked. After "fixing" it, they decided to go in warp mode. I knew what to check this time:
army->x = sx; // changed the wrong coords :P
army->y = sy;
army->dx = x;
army->dy = y;Then they started to move! But some of them disobeyed and went in the wrong places. Since I haven't coded AI yet, I knew it was a bug.
if (army->x < army->dx)
army->x++;
else if (army->x > army->dx)
army->x++; // --
else if (army->y < army->dy)
army->y++;
else if (army->y > army->dy)
army->y++; // --That's my "path finding" code. I think I should quit for the night. This might get ugly.
-
bug hunting complete
I believe I've killed all the bugs related to moving troops. If two armies of the same lord end up being idle on the same place, they get merged together. However, two or more armies (of the same lord) can occupy the same space if they are both going places.
Castles also have idle troops. The code got messy fast because I didn't plan for it. I'd rather have had one way to represent idle troops. As it is, I first have to check if there is castle->soldiers and then if there is any idle armies at the given location and get the army->size. There can never be an idle army inside a castle, nor can there be two idle armies on the same space. So it's more complex than need be, but that's gunna be how it is.
This is the nasty code that merges armies after the moving is done:/* merge any idle armies together */ army = map->armies; while (army) { if (army->idle) { if (map->castle_lookup[army->y][army->x]) { /* let's place this troop inside the castle */ map->castle_lookup[army->y][army->x]->soldiers += army->size; army = army_remove(&map->armies, army); /* returns the next army */ continue; } else { /* we can start with the next army, because previous ones have already been checked */ ARMY *army2 = army->next; while (army2) { if (army2->idle && army2->x == army->x && army2->y == army->y) { /* two idle armies on same title */ if (army2 == army->next) { /* gotta do this, or else army's next pointer is pointing to junk */ army->next = army2->next; } army->size += army2->size; army_remove(&map->armies, army2); } army2 = army2->next; } } } army = army->next; }
That's it for today. Tomorrow morning I hope to have the game finished. Then I can decide if I want to clean code up, add a proper AI, or maybe do some networking.
-
The second day
I woke up at 9AM local time, which wasn't too bad. Probably means I won't finish my game this morning as I would have hoped. It took about 30 minutes to do some various admin tasks, and now I've got breakfast to eat. So hopefully I'll be back at it by 10AM.
A few people have had some questions regarding scaling up an internal resolution to a larger one. The following methods are perfectly fine:- Setting a 320x240 resolution and adding 20 pixel black bars to the top and bottom.
- Setting a 640x480 resolution and stretch_blitting the 320x200 game resolution.
- Setting a windowed mode at 320x200 or any multiple and stretch blitting
In regards to the 320x200 rule:If you choose to stretch_blit(), the default settings must not contain any type of smoothing. Remember, you only have 16 colors to work with anyway. If you want to add a smoothing as an option, feel free to do that. It can even use over 16 colors if you want.
Also, if you are using graphics (3D or otherwise) that scale seemlessly, the default resolution must be 320x200 @ 16 colors—and playable. (You can use the same stretch_blit approach as well.) You can include higher resolutions and colors if you want.
In regards to the 6 color rule:
I'm personally not going to be counting your colors and calculating the hues—just be honest. You can have up to six visible colors; you can use a seventh for masking purposes. As long as the colors look the same shade, you don't have to worry about the exact hue values. - Setting a 320x240 resolution and adding 20 pixel black bars to the top and bottom.
-
Attack Mode
Took me a while to get going this morning, but I'm at it now. Armies can attack now, but no fighting occurs. I added a couple shortcut function to deal with the multiple way troops are represented:
/* A short cut function that checks for castles or troops at a given location */ int map_get_enemy(MAP *map, int x, int y, int player) { return map->castle_lookup[y][x] && map->castle_lookup[y][x]->player != player ? map->castle_lookup[y][x]->player : army_get_enemy(map->armies, x, y, player); } /* A short cut function that returns the number of troops and castle soldiers at a given location */ int map_get_enemy_size(MAP *map, int x, int y, int player) { return army_get_enemy_size(map->armies, x, y, player) + (map->castle_lookup[y][x] && map->castle_lookup[y][x]->player != player ? map->castle_lookup[y][x]->soldiers : 0); }
As you can see, there's no graphics for attacking. I need to add little tick marks around the castle or army being attacked. I realized I had no image editor with a decent palette editor, so I just downloaded Tile Studio. It should do what I need it to.
-
Version 1.0 is Released!
I finished up the game and have uploaded it. As it is now, it is pretty much exactly how the original game played—except that I have not implemented any AI for the rebels.
In the original game, the rebel (black castles) didn't start moving until later in the game. It really is meant to be a multiplayer game.
Now I will break for lunch. I will contemplate adding path finding, AI, or networking.
Or if I get lazy, I'll just leave my entry as is.
If you want to play it now, you'll need a recent version of Allegro to compile it as I use the load_font() function and some _ex() functions. I'll provide a binary at the end of the compo. -
Title Screen
I'm leaning toward trying to add Network play. Maybe if it goes really bad, I'll implement a good path finding algorithm instead.
In the meantime, I created a title screen, with the help of Google Images and The GIMP. -
Compatibility Test
I've tried it out under Mac OS X, and it works great! OS X can now forever be known as a gaming platform. I've been told it works under Linux as well.
(The current source as uploaded requires a #define to compile under Linux/Mac.) -
Power Button for Gamepay rule
A question was asked regarding how strict the "four button" gamepad rule is in regards to shortcut keys, specifically if ESC could be used as an exit key. The whole point of the rule is that you have no shortcuts to rely on. Therefore, the answer is no.
However, there is one exception. You may use the ESC key to automatically shut down the game immediately. In other words, as soon as the user presses ESC, the game quits. You can implement it gracefully in your code to allow for a clean shutdown, but you cannot prompt the user. Think of it as the power button of a console.
Ideally, you should have a START button that acts as pause. The user should be able to use the SELECT button to choose quit. If that doesn't work out, feel free to use ESC as an immediate shutdown. That's the only exception to the "four buttons" rule. -
Sound Effects
And updated version with sound can be found here:
http://www.matthewleverton.com/games/lords/RebelsAndLords.zip
It includes a Windows binary, so it is too large to upload here. The effects are so bad, it's worth listening to.
-
Enter War Room
Since my game is turn based, I thought I'd try to implement some networking. I've never done this before, and it's getting dangerous.

I don't know that I'll actually get it working, but at least you can chat. Unfortunately, due to the low resolution, there's not much room for a nice GUI. I wouldn't have made one anyway.
If I do get around to making this work, it will be command line driven. /create game would start a game. /join matthew would join my game. If I don't get it working by Monday, I'll probably implement it for fun later. -
Networking making some progress
I started too late on the networking and have had to spend too much time creating a layer of code above enet to assist with serializing packet data. The chat is fully functional, but I haven't gotten to the create game / join / play code yet.
So it's doubtful that it will make it in time for Monday, but we'll see. I'll be back in 8 to 10 hours. -
Let's Play!
I've been back at it for an hour now. I had some ugly bugs in my linked lists. It wasn't too bad, considering I wrote the code early this morning at 4 AM while chatting on #speedhack. Once I got those fixed, I was able to start adding my commands quickly thanks to my serialize()/unserialize() functions I wrote to sit on enet. Basically, I can create a PACKET_BOX structure and add ints and strings to them. The receiving side will get the PACKET_BOX serialized. After unserializing, it can retrive the data back in the same order it was packaged.
There's not enough error handling to make it a safe experience, but I can trust my fellow speedhackers, right? Uhm, maybe this isn't such a good idea.
Attached is a screenshot showing how the C64 style interface works. Current commands that are working include:- help
- create
- join
- games
- quit
Now that people can create and join games, I need to actually write the networking code for the game. I'm planning on setting up Player #1 to be the master, and all the other players are basically just dumb terminals that can send move inputs.
I've never done a network game before, so I hope it works out. -
Do you see what I see?
Finally, the clients are all talking to each other. I have a Linux server that acts as the chat room host and a relay between all the clients. Clients are notified via UDP when data changes.
The host (first player) acts as the server, so if you want to cheat be the host. The clients are told the bare minimum of information they need to paint the screen.
In the screenshot below, one of the windows is Player 1 (host) and the other Player 2. Player 1 drew the random map and then sent it to Player 2. Although Player 2 can see where all the castles are, he is not able to see the size of troops inside there.
While this makes it impossible for players to cheat, it means I have to implement the game engine three times: hot seat, server, and client. I also had to make the Linux lobby server. It thankfully is "complete" because once the game starts, all it does is relay all data back and forth. -
Why won't you listen?
After taking three hours off, the problem I was having didn't correct itself. Basically, I'm to the point where I need to send private data to some of the peers, but it's getting lost somewhere. So if any of you notice any lost UDP packets, please point them in the right direction. Thanks.
-
Much Better
Shortly after posting my last entry, I realized that I had allocated only two channels for the network, but I was trying to use five. The highest three are used for the master to send private data to each of the other three players.
Time to see what I can hack together in these midnight hours. -
The first net move
Taking this one step at a time... The host can make a move after telling the others to go. The others don't actually listen to the request. In the screenshot, the top window is the host making his move. The other window is a client that doesn't realize he can move, because I haven't coded it yet.

I forgot to crop the image, so you get to see both my monitors, including some lovely code. -
Almost there!
The multiplayer mode is coming along nicely. I still have some data sync issues to work out, but I think I'll get it worked out. I want the the network play to be "solid" under the assumption that everyone is playing nicely.
The screenshot shows three people playing a network game after the first move. -
Completed!
The networking is complete enough to make it into the SpeedHack version. It's probably only playable if all the players have a secondary form of chat, because there is no in game chat. Also, there is not any information regarding when clients have disconnected or are idling, etc.
I'll touch it up abit if time permits, but now I've got to create the readme.txt's and all that fun stuff. -
Rest in Peace
It's 6AM with an hour to go. I've packaged up my entry and confirmed that it works under Windows and Mac OS. It should be fine on Linux then. There is online game play, and I'll keep the lobby up until it crashes.
Just be nice to it. The game tends to crash online after a while. There's hardly any error handling. My code is a complete mess, which is a shame considering I'd like to polish the game up a bit.
That sums it up for this year's SpeedHacking! Thanks to everyone who participated this year. Stay tuned for information on how winners will be judged.
For now, I'm off to bed...