Thursday, 23 April 2015

Simple Village Generation

Although I will be improving the village generator that I used in HarvestRL, this post will share my original method. It was rather simple, so people who want to quickly throw together a village might be interested in this.

First, here is what a typical village in HarvestRL looked like:

For those unfamiliar with dungeon generation, realize that you can use those algorithms to create pretty much anything even if they aren't supposed to be dungeons. That's a hint for what I did here. The full process worked somewhat like this.

1) Determine the space on the map to use for the village.
In this case, I used a random width and height between 40 and 60 tiles. This variation helped to keep the village from seeming too similar each time, and it also varied the population numbers.

2) Make a road into the village.
I picked a random point in the middle of the Southern edge of the village and created a path that went through that point. It started at the edge of the village and went into the middle of it. The end point was also randomized so that it didn't always stop right in the middle of the village, sometimes it stopped a little short. Then, I generated the other half that went from the edge of the village to the edge of the map. Once the path got a certain distance away from the village, I had it meander like a river. The path always led south out of the village, because I didn't want to make the farm's starting location too random.

3a) Divide the village space.
I used a Binary Space Partition (BSP) algorithm to break up the village area into smaller chunks. Libtcod already provided this. Defining the smallest space to be about 8x8, I worked with 3 levels of divisions to create a series of spaces. These I saved as rectangle objects. Although you could use the generated BSP Tree to store the connections between these rectangles, I didn't do that.

3b) Organize the partitions.
Each rectangle was a "plot of land" for a villager on which a building would be placed. The size of the building was randomized further (an inner rectangle), so that the spacing between buildings would be non-uniform. I stored this inner rectangle as a separate value in the same Building object (which at this point had two values: the rectangle for the plot of land, and the rectangle for the building). This step was performed while iterating over the leaves of the BSP Tree, and then I discarded the Tree since I didn't need it anymore.

3c) Discard rectangles over the village path.
Since the path was generated before the partitioning, each rectangle was checked to see if it overlapped with the path. If it overlapped the path, I didn't save it. This guaranteed an empty space where the path went into the village, so the entrance wouldn't feel too crowded. Since the rectangles varied in size and position, this could also affect the number of buildings (and hence population) in the village.

4) Randomize the type of building.
I made an enum containing all the types of buildings that I wanted to have in the village. Then, I added the required types of buildings to a list (in my case, the Harvest Shrine and the Shop), filled 3/4 of the list with homes, and then filled the remainder with random picks from the list of building types. A full list was equal in size to the number of buildings that were created. This ensured I had a safe distribution of homes, businesses/specialty places, and quest-required buildings. Due to lack of time on the 7DRL, most of the building types just reverted to homes.

5a) Assign building types.
At this point I have two lists: one of all the Building objects, and one for all of the building types to be created. Both lists are equal in size. First, I picked the largest building and made it the Shrine (the first building type in its corresponding list); obviously, this is not necessary for other games but it shows that the generation order does not have to be random. After this, I iterated over the list of buildings and gave each the next entry on the building type list. Thus, I could guarantee how many buildings of each type were created, and keep the possibilities random; the random choice of building types occurred in step 4, while step 5 decided where that building type would become instantiated in the village. This step could be improved, such as assigning types based on the relative positions of buildings, but it worked well for a quick village.

5b) Orient the building.
As I assigned building types, I also oriented the building. I picked a random edge of the building, labeled it the front, and stored that value (I just used a direction enum, the same enum used for movement directions). This step could be done more intelligently; for example, buildings close to the middle of the village would face outward and buildings near the edge of the village would face inward. You could easily calculate what is inward vs. outward by looking at the closeness of the building to the center of the village. I just left them random, except for the Shrine that always faced South.

6) Instantiate the building.
With all the details decided, I iterated over the building list and changed the terrain of the map. The outer rectangle was filled with grass, the edge of the inner rectangle was made a wall, and the inside of the inner rectangle was made a floor. Then I picked a random spot along the front wall, that was one tile away from either edge, and made that spot the door. A short dirt path was created from the door to the edge of the land plot. Some furniture was randomly placed in the building (which looks strange at times, since it's too random) and a random number of inhabitants were created (between 1 and 3).

The furniture and number of inhabitants was dependent on the building type. So, when you're playing the 7DRL and you enter a building containing one person and no furniture, that's because the building was not actually a home. Note that building types could also be other village features, like a graveyard or a garden or a fountain. Again, I had that in the code but never finished it so sometimes you'll find a village with big open spaces between buildings. For a more intelligent method of creating interiors, you could use plans that can change in orientation. The only plan I had was for the Shrine, but it was so hard-coded that I couldn't change the orientation (hence why the Shrine had to face South). I had already spent enough time on other stuff in the game that I didn't want to make the room plans better, but I can do it now.

7) Create a town wall.
I thought about doing this but didn't in the end. However, it is pretty easy to add if you want. You already have the borders of the village saved, so just create a wall around the edge of it and leave an opening when you come across the path.

So, that's the algorithm in a very broad sense. Since it uses BSP it still seems somewhat blocky, and that's why I want to use something different in the Extended Edition of Rogue Harvest. However, if you want to generate a village with a few hours of coding then this works. You'll need a BSP implementation, but you might be using that for dungeon generation anyway.

On that note, the area around the village was generated in an even simpler way. Notice that the edges of the map are non-uniform but in a somewhat smooth manner:

What dungeon generation algorithm does this? The Cellular Automata one, that's what. I created a grid with a one-tile border, randomly seeded a few other places, and ran the automata algorithm a few times. Then, I took it and used that to create the edges of the map (the mountains) and rocky places in the middle. This created the valley for the village, and it was created before the village; that way, when I generated the village, terrain around the village could be cleared and buildings wouldn't be lost to random mountains cropping up in someone's backward.

I also used a random seeding of the same grid, and ran it just once to create the grass and stones that litter the valley. Even though you don't need to have something as elaborate as this for open wilderness areas, I highly recommend having something other than stretches of plain grass (the .'s in my case). With a map as big as this game used, having pure grass looks very unappealing. A similar problem could exist with too much variety though, or having a display with confusing meaning; for example, using lower-case letters to represent enemies as well as trees and other wilderness features could be confusing for the user to interpret.

So, there you go. This whole process took me about 5 or 6 hours to think of, plan, and code. While it definitely has some areas for improvements, it's pretty good for a simple outdoors village.

Sunday, 19 April 2015

UI Redesign

Given the reviews from the 7DRL Challenge, and my own annoyances with the previous version, I have started the remake of Harvest RL by changing the UI.

First, I wanted to add mouse support. This has been the brunt of my work so far, mainly because of how I coded the UI to begin with. At this point though, mouse support is almost complete. The last thing I need is to get mouse targeting and looking to work properly. Then I'll add the Game Options screen to allow disabling of mouse support (for those who really dislike it) and call that feature complete.

Second, I wanted to change the inventory. There were several complaints about using shift+t to throw items, as an example. Although I had little difficulty with upper-case letter commands, I want to address it for others. The reason I chose this control scheme was so that lower-case letters could be used to select an item, and then upper case letters would interact with the chosen item. After thinking about it more, I realized that I could just use a separate window for the chosen item with the necessary commands. That way lower-case letters could be used for both item selection and item interaction. Two key-presses are needed for things like throwing anyway (even if you use "throw" + "choose item"), so I just needed to make minor changes to the inventory for this to work.

There's a picture of the new inventory screen here. I also added the ability to view (and remove) equipment and put in buttons for the mouse, instead of just key-command tooltips. I'm not satisfied with the button coloring yet, but their functionality is good.

Third, I wanted better info for allies and enemies. There is now a list of enemies on the screen, with health information. Attitude and status effects will be shown there too, but right now that's not even included in the AI yet. After I restore the status effects that I took out from my previous framework (due to it not working right) then I can get hunger, tiredness, and stunning connected to it. That should greatly improve some of the UI issues with those things. Hunger and tiredness need mechanical changes, but I'll work on that later.

Lastly, some people might notice that I'm using a different font. Although I particularly liked the previous font (it's the one I use for Dwarf Fortress all the time), the sizing of this new one gives me a lot more options. I could take inspiration from CogMind and use multiple fonts, but I'm not going to; I'm already experimenting with a different library for drawing routines, and it will cause any work that I do on multiple font rendering to be useless.

This is then the official start of a new version of this game, which I think I'm just going to call Rogue Harvest: Extended Edition. I might change the name later, but it's the tentative name for now. Once these minor UI changes are working properly, I'll put up a proper development plan and do more regular updates.

Saturday, 4 April 2015

HarvestRL New Update

As it turns out, there were still several bugs in the previous version, some of which were quite major. I fixed these, added a better intro screen, and greatly optimized the loading times. This may have introduced a minor loading bug, but that's not too important for me. As of version 1.02, I am considering this game complete. It's not great, but it's finished.

That being said, I am taking this and expanding it into a new game. I'm trying to decide if I want to call it HarvestRL2 or HarvestRL:X (for expanded) or just a totally different name. The goal will be similar, but with a different time scale. Currently you can finish the game in 10 or 15 days (potentially even 3 though most of the village dies in that scenario), and I wanted something longer to bring about more interesting aspects of the farming.

In addition, there are major UI problems. The ASCII stuff is fine, and even the way I've displayed information works, but the control scheme does not. I'm going to experiment with a different library since I'll have to make some major changes anyway, see where that takes me, and go from there. I plan to merge the code from this project with another one that involved random world generation but never saw the light of day.

For now, you can get the latest version of HarvestRL here.

Friday, 20 March 2015

HarvestRL Update

After taking a break for a few days, I went back to the code for HarvestRL and started making some revisions. There were some rather major bugs that made the game impossible to complete at times. In other cases, the game was exceptionally easy (though this was a rather circumstance). I've gone through and fixed what I thought were the major issues with the game.

So, version 1.01 is now available for download. The full details are available here.

Wednesday, 18 March 2015

HarvestRL Postmortem

With the challenge officially done, it's probably a good time to reflect on the game. It needs polish, and I'll have some fixes and adjustments done for those.

Rather than just growing crops for money or whatever, I wanted there to be an actual point to it. One aspect of this was growing food to keep a food-clock in check. Having the player be so hungry that they need to eat every second was just plain annoying, and it made far more sense to have the player grow food for the village. Initially I was going to have the option to sell food to a merchant (for money) or donate it to the village, and have that as a choice. The selling never made it into the game, so it's just an issue of donate it or keep it to eat. The overall clock is what I intended in the game; currently, it's too easy. There isn't enough pressure that the player needs to decide what to do about it since food is too readily available.

The combat is sufficient though tactically shallow. The player has very few hit points for several reasons. I wanted no randomness in the combat. I wanted each opportunity to be hit to be significant. I wanted damage reduction to be limited. As a result, the player should regularly get swarmed and then have to figure out where to go to avoid getting quickly killed. This becomes less of an issue near the end of the game (again like I wanted it), but the final boss is still exceptionally difficult. Unfortunately, it's difficult in a tedious rather than tactically interesting way. However, this is because of another issue.

There's no consumable combat-related items except healing and a weak ranged attack. The ranged attack is certainly useful (especially since it's the only non-renewable resource in the game), but even a few more special effects would have made a huge difference. Unfortunately, the framework I had in the game wasn't working with special effects yet, so I just hardcoded these two quickly (along with the seeds) and left it at that. Later versions will definitely need more, and a greater variety of enemies, to deepen the combat. That is definitely the weakest part of the game right now.

I also really dislike the village generation, but I spent a whole day on it and didn't want to lose any more time for the challenge. The underground levels are actually close to what I initially intended. They're not great, but I didn't want something fancy anyway. It is annoying that you can get an unwinnable game due to the RNG, but at the time I wasn't thinking about such an issue.

Overall, I'm content with my first successful 7DRL. There's a lot of room for growth with this game, but I'm torn between doing regular updates to HarvestRL and turning it into something more versus renaming it as a new game and pushing the boundaries on it. I'm leaning more towards the latter choice though.

I can also integrate this game with others I've started over the past few years but never finished or released. Since I now have something available, and have a means of updating and releasing new versions of things, you'll start seeing more games from me in the months and years to come. Hopefully, that will be a good thing.

Monday, 16 March 2015

7DRL Challenge 2015 - Finished

The challenge is over, and my entry is complete. I had some really frustrating compilation problems near the end, making a redistributable version impossible. That was fixed this morning, but it involved a lot more work than expected.

HarvestRL is the finished game. You play as an adventurer/farmer tasked with saving a small village. Some of the villagers are possessed by an evil spirit, and the rest of the villagers are too scared to do anything. You need to find the sacred fruit that will cure the villagers, while in the meantime keeping the village stocked with food. You also need to eat, but you can grow food or find some in the wilds. When you've cured the villagers, you need to find a defeat the source of the evil.

This is meant to be a short game, but I really don't know how well balanced it is. It could be very hard or very easy depending on how you play, but at least you can actually win it. All the instructions are in the game itself, except for the location of your farm (SouthEast) and how to get seeds (eat food).

You can download it here:

Windows 32-Bit

I'll likely do more with this game in the future, or use parts of it in other games, but for now it stands on its own.

Friday, 13 March 2015

7DRL Challenge 2015 - Day 5

This is now the start of Day 5. Despite the long list of things I would like to add to the game, most of it is still coming along smoothly. Yesterday was spent fixing the inventory system (since my previous framework had everything needed for one, but it was broken) and getting farming to work. Basic combat is in the game, but I want to make a few adjustments to it before I'll consider that ready. The AI shouldn't just wander all over the place no matter the circumstance.

Currently, you are able to do the following:
- explore a random overworld with a village
- head to rather empty but random dungeons
- run into villagers' houses and close the door behind you
- till soft soil with a plow
- plant seeds in tilled soil
- water planted seeds and other plants to keep them wet
- attack random rabbits and wolves wandering in the world

The game has a day-night cycle and changing seasons, but they don't look different yet.

Currently, farming works as follows. Using a seed (like a potion or something) scatters seeds all around the player. Only certain tiles are affected by seeds, and these get a "planted seed" decoration placed on them. You can operate the plants with a watering can to get them wet. The next dawn, if the plant is wet then it will grow. After it grows for a certain number of days, it changes into a plant ready to be harvested. The player then bumps into the plant and harvests it (adding the item to your inventory). This is very data heavy, as anyone looking at the config files will realize, and there could very well be a better way of doing this. However, this was easy to program; I'll improve it after the challenge if I keep working on the game.

This system is also much easier than my previous plan. I thought it'd be good to turn on a "farming" mode, it asks you what tool to equip, then you toggle on and off the use of that tool as you wander around. Instead, you now just equip the tool you want to use and then automatically use it as you walk into or onto various tiles.

For today, I need to add more content. You need to grow more than just one type of plant, the plants need to do something, the village and dungeons shouldn't be empty, and so on. This will be the same for tomorrow, so that Day 7 just involves bug fixing and UI cleaning. I'll post again tonight with some updated screenshots.

Wednesday, 11 March 2015

7DRL 2015 Challenge - Day 3

It is now the end of the third day of the challenge for me, since I started later than most of the participants. Happily, others are also on their day 3, so I don't feel that behind everyone.

The plan for yesterday was combat, enemies, and entering/exiting the dungeon. That didn't quite work out. Instead, I spent most of the time getting multiple areas to generate, moving between them not breaking the game, and having a nice village show up. The village is still way too random looking for my taste, but I can fix that later if there's time. At least it works. The end of day 2 thus brought no combat but it did bring a semi-interesting world to explore.

Day 3 started with the prospect of adding the farming. Since this is supposed to be a game with some farming elements, I thought I should probably add that. I ran into UI difficulties almost immediately, much more so than I expected, and that consumed most of my time today. Fortunately, those problems are fixed. The player can now explore the world, look at things, open and close doors, and switch in and out of farming mode.

In Harvest Moon and games like it, you typically have a variety of tools that you switch between and then use them on the tile in front of you. Since I didn't want to add facing to an ASCII game, that meant two possibilities: 1) have a use+direction for each farming action, or 2) have an auto-use for some item wherever you move. I am going with option 2. Option 1 is (barely) easier to code but it would be exceptionally tedious to play. (Who wants to use three discreet button presses for each farming plot they want to water?) Hence, the player will switch into and out of farming mode. This mode will equip a selected tool, allow auto-using wherever they walk (or bump into as may be the case), switch tools, and toggle the auto-using. There might be a better way of doing this, but that's how I'm going to develop it.

So, in the meantime, here are a couple screenshots of me wandering around and opening doors.

Tuesday, 10 March 2015

7DRL 2015 Challenge - End of Day 1

The first day went about as well as I expected. Numerous coding issues, minor problems that broke everything else, and so on. At least I didn't have compiler problems, which used to be a recurring issue every time I started a new project.

Fortunately, the first day ended with the basic functionality complete. A randomly generated level is drawn, multiple levels are stored, the player can move around on the screen, supporting and messaging information is displayed, and players can easily get into and out of the game.

For day 2 I plan on accomplishing: basic combat, enemies, and entering / exiting dungeons. The enemy AI won't be particularly impressive at this point, but it can be improved later. The dungeon generation is also rudimentary, but that is also acceptable for now. If all goes well today, there'll be some fancy screenshots ready for day 3.

Sunday, 8 March 2015

7DRL 2015 Challenge

Last year I joined the Seven-Day Roguelike Challenge (7DRL) in which participants attempt to make a Roguelike game in 7 days. I completely failed by day 5, having only the most rudimentary part of the game finished. I did have some random levels to explore and wandering opponents, though it was stuck in a real-time mode (for some reason) that made it completely unplayable.

This past game was using an engine I had built for Roguelikes, but the engine was very incomplete and buggy. Since then, I had been working on it occasionally and trying to use it for some other game. Neither the game nor the engine made it to any stage of completion worth releasing.

This year though, the engine was actually complete enough that I thought I'd finish major parts of it by using it in a 7DRL. This made sense for the following reasons: 1) the engine was meant for a large game, 2) a large game is not going to be finished by me anytime soon, and 3) making the engine work for a small game means finishing the essential parts of it. Since the small game will have all the things that a RL needs (e.g., random level generation, exploration, combat), then this challenge will give me the opportunity to actually finish those things.

To make sure this was even possible, I spent the past week fiddling with the engine and making sure the basic structure was still good. More work needs to be done, especially with the enemy AI, but I'll work on that as part of the challenge. Even if I fail again, at least the engine will be more capable for next time.

For 2015 then, I'll be working on A Rogue Harvest. It will be a procedurally generated simplified version of Rune Factory (the Harvest Moon game with combat and non-farming activities). Combat will be somewhat straight forward, but the farming mechanics will be tied in to it. You will need to choose what food to grow, and that food will help you accomplish the story missions (the dungeons to clear out). I have many ideas to expand on this game, but I'll add those later if the game is actually completed on time.