Skip to content

An ASCII rogue-like for the terminal with auto-generated maps, dungeons, castles, 70+ enemies, 50+ items, 20 levels and a simple but fun combat system!

License

Notifications You must be signed in to change notification settings

LiquidFun/Aceth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aceth - an ASCII rogue-like written in C++

This is a project I wrote back in 2015, this was my first fairly large project I did when I was learning programming. I rediscovered it and saw that it was actually fairly feature-full. Although the code quality is terrible to say the least. The entire project consists of a single file of 3000+ lines, without a single class or struct. Everything is in methods, which are all called in a single game loop. More on the funny code stuff I found later, first let me show what it looks like as it is still a bit of fun.

Showcase

Starting area randomly generated

Exploring a cave to find chests (yellow C), but unfortunately we stand right in front of a skeleton (red e) and a biter (red 7)

Starting a game and trying to attack a wolf, which is still too strong so we die and respawn

High-level gameplay of exploring a dungeon and finding the dragon guarding it's treasure

Features

  • A map generator which creates various biomes (forests, swamps and even arctic wastelands) as well as caves, castles and villages
  • 77 different enemies which spawn in various biomes depending on the player Level
  • 20 levels the player can attain
  • An inventory system with 5 different types of gear the player can find or buy
  • A fairly simple combat system
  • Hacky async movement of enemies while idle
  • A day and night cycle which makes your view-field smaller during the night
  • Various help pages for enemy-types, terrain types etc.

Playing

Compile and create the maps, then run the game in the game directory:

With make:

make
./MapGenerator
./Aceth

**Note that without creating maps you won't be able to create a new game**

If you have a wonky color scheme in your terminal like I do where red is yellow, blue is gray and yellow is dark purple then you can use tput init to reset the color scheme, which makes the game colors accurate again.

Alternatively just compile the src/main.cpp and src/MapGenerator.cpp files and place the executables in the cloned folder so it has access to the saves and data folders.

Guide

If you do actually want to try it out, here is a short guide: during the first levels it's advisable to explore a lot and find treasure chests (C) which contain money and items. Explore all caves (c) and houses especially (h). In the caves there are a lot of chests, be careful of stronger monsters though. In the houses there are potion shops (p) and item shops (S). Definitely check them out and buy potions frequently. Try to fight easy monsters without dying, use (h), (j) and (k) for help in finding what monster you are facing. Remember to equip better items as soon as you get them by pressing (i).

Funny code I found while looking at the project

As mentioned previously the code is awful. I appreciate it as a reminder of how much I have improved during the years.

Version Control

Back then I didn't know about git, so all my backups looked like this:

└── Quest for Something - 500x500
   ├── backups
   │  ├── main -2015 02 17   22 50.cpp
   │  ├── main500 2015 03 01   23 17.cpp
   │  ├── main500 2015 03 01   23 54.cpp
   │  ├── main500 2015 03 03   16 26.cpp
   │  ├── main 2015 02 15   22 50.cpp
   │  ├── main 2015 02 16   00 30.cpp
   │  ├── main 2015 02 16   12 35.cpp
   │  ├── main 2015 02 17   00 47.cpp
          ...

And there were multiple folders like this, the only way to know in hindsight which the newest was, was to check the LOC in the main.cpp file.

I also had no understanding of classes or OOP for that matter.

Couple of examples

Very verbose way to write showTips = !showTips:

if (showTips == false)
{
    showTips = true;
}
else if (showTips == true)
{
    showTips = false;
}

Having no idea what seeding means I always seeded before every call, so I had problems of always getting the same values as long as it ran the same second. So I counteracted this by using the current tick count in milliseconds, which kind of 'solved' the problem. I also added time(0) multiple times as well as some arbitrary number...

default_random_engine randomGenerator(time(0) + time(0) + time(0) + GetTickCount() + myRan);

Instead of finding the line count from the files, or even from the filenames I separately encoded the line count.

const string loadItemsFile = "data/itemList52.tsv";
const string loadSpellFile = "data/spellList13.tsv";
const string loadEnemyFile = "data/enemyList77.tsv";
const int ITEM_AMOUNT = 52;
const int ENEMY_AMOUNT = 77;
const int SPELL_AMOUNT = 13;

The longest 3 lines in the file have 403, 385, 318 characters respectively. Which is just slightly more than the recommended 80/100/120.

cat src/main.cpp | awk '{print length($0)" "$0}' | sort -n

In fact there are 23 lines with more than 200 chars.

cat src/main.cpp | awk '{if(length($0)>200)print length($0)" "$0 }' | wc -l


There is a lot more stuff like this in the code, I really felt an urge to correct the stuff, but I decided against it. So it remains as a valuable history lesson for myself :)

About

An ASCII rogue-like for the terminal with auto-generated maps, dungeons, castles, 70+ enemies, 50+ items, 20 levels and a simple but fun combat system!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages