Welcome to a ncurses-free boost-free text-based replica of the Hearts of Iron (not really), one of the most intricate game of the century, where you build and devour other countries.
Yung Chin Pang Sam 3035778682
Wu Ziliang Louis 3035787061
- Quick Start
- Goal
- Progression of game
- Map design and coordinate system
- Technical details
- Advice for beginner
- Other details and tips
- Saving and Loading
- Random levels
- Implementation
- Flow ( read this before going to the codes )
- Testing and development ( read this before going to the codes )
Note, this is a linux-version only game and you are to run this game only on linux platforms.
Recommended terminals (restart the terminal if you experience flickering): vscode, putty for ssh, ubuntu 18 (system terminal)
First, clone the repo by
git clone https://github.com/samyung0/ENGG1340GP107 hog
Then cd in and make (may take around 100s depending on your pc)
cd hog && make
Then start the game and enjoy (or suffer depending on how well your play)
./main
Your objective is to capture all countries in the map within a time limit. A country will capitulate once 70% of its land are captured.
Default game speed is 1 day per second. You may change it in the settings or when in game.
You can perform the following actions anytime during the game:
Simply put, getting more buildings will boost your resources available for building more buildings and training troops.
Researching does not take any resources except time which varies from different types, some may give attack bonus or unlocking building upgrades just to name a few.
To prepare attacking, you must first train some troops. You may group them into different armies to make it more organized.
You can initiate an attack at anytime by either assigning individual troops or an entire army. Each troop has their own hp and will regenerate at an intial rate of 1 hp (base) per day when not in full health. Note that other countries will not attack you, only you will be the one attacking.
You can attack many blocks at the same time but you can ONLY attack 1 country at each time.
The outcome of the battle depends on the types and amount of troops you and the enemy have, the attack bonuses, the air support and the terrain, etc. (refer to Battling for more details)
By capturing a block, you will receive the acquirables of it (different buildings and land).
When you have successfully captured 70% of the country's land, you will conquer the country and receives all its acquirables.
For other countries, you will see the different regions of the other countries represented in coordinates, from A1, A2, to Z10, with A representing the outskirts of the country and B, C,... being the land deeper into the country. You must attack the country layer by layer (form A to B to C, etc) when pushing inwards. You may attack any blocks horizontally. All regions must be at least connected adjacently so there must be a way to attack any blocks eventually.
For your own country, you will not see a coordinate system since you will not get attacked.
Exmaples of enemies' map:
A1 A2 A3 A4 A5 A7 B2 B4 B5 B6 B7 C2 C3 C4 C5 C7 D1 D2 D5
A1 A2 A3 B2 B4 B5 C2 C3 C4 C5 C6 C7 D1 D2 D5 E1 E2 E4 E4 E5 E6 E7 F1 F2 F7 G1 G7 H1 H2 H7
-
There are a total of 5 buildings that you can build, each occupying different amount of land and requiring different number of manpower to work on with different time to finish, and having different upgrades:
Note the manpower will return once the building is finished. It is not actually gone when you use it.
Also, land is limited and you may need to remove some buildings when insufficient.
- farm (land: 3, manpower: 1, 10 days)
- civilian factory (land: 1, manpower: 1, 10 days)
- military factory (land: 2, manpower: 2, 15 days)
- training camps (land: 1, manpower: 1, 10 days)
- airport (land: 1, manpower: 4, 45 days)
To provide food for troops. See Troops training for more info on how much food a unit needs.
Stage 1 : land: 3, manpower: 1, 10 days, provide 8 food
Stage 2 (locked): land: 5, manpower: 1, 10 days, provide 20 food (unlock by Intermediate Farming research)
Stage 3 (locked): land: 6, manpower: 1, 10 days, provide 28 food (unlock by Advanced Farming research)
To provide the manpower needed to build other buildings. Initial amount varies from levels.
Stage 1 : land: 1, manpower: 1, 10 days, provide 1 manpower
Stage 2 (locked): land: 1, manpower: 1, 15 days, provide 3 manpower (unlock by Intermediate Division of Labor research)
Stage 3 (locked): land: 2, manpower: 1, 15 days, provide 5 manpower (unlock by Advanced Division of Labor research)
To provide the equipment needed to increase the strength of the troops.
Stage 1 : land: 2, manpower: 2, 15 days, provide 10 equipment
Stage 2 (locked): land: 3, manpower: 2, 30 days, provide 30 equipment (unlock by Intermediate Production Line research)
Stage 3 (locked): land: 5, manpower: 4, 60 days, provide 100 equipment (unlock by Advanced Production Line research)
To train the troops. Each type of troops requires different number of training camps, refer to Troops training for more details.
Stage 1 : land: 1, manpower: 1, 10 days
To allow planes to be built. 1 airport can support exactly 5 planes, not matter the plane type.
Stage 1 : land: 1, manpower: 4, 45 days
-
You can do research anytime during the game but only one at a time. Each research will give you different bonuses and unlocks upgrades but also require different time to finish. The following shows all research that you can do in all levels. It always follows the path of rudimentary (what you initally have) to intermediate to advanced.
Farm:
Division of Labor
- Intermediate: 20 days (unlock level 2 civilian factory)
- Advanced: 30 days (unlock level 3 civilian factory)
Production Line
- Intermediate: 15 days (unlock level 2 military factory)
- Advanced: 30 days (unlock level 3 military factory)
Land Doctrine
- Intermediate: 40 days (+20% damage dealt by each unit of land troop)
- Advanced: 40 days (+30% damage dealt by each unit of land troop)
Air Doctrine
- Intermediate: 70 days (+40% damage dealt by each plane)
- Advanced: 100 days (+60% damage dealt by each plane)
Urbanization
- Intermediate: 50 days (+10% land available for building, rounding off)
- Advanced: 70 days (+30% land available for building, rounding off)
Weapon
- Intermediate: 20 days (+5% attacking damage for tanks)
- Advanced: 70 days (+10% attacking damage for tanks and planes)
Training
- Intermediate: 30 days (-10% training time required to train any unit of land troop)
- Advanced: 50 days (-20% training time required to train any unit of land troop)
Recovery
- Intermediate: 30 days (Total 6 recovery per troop per day)
- Advanced: 50 days (Total 8 recovery per troop per day)
-
You can train any amount of troop anytime given you have sufficient resources. There is no cap of how many troop you can have, but do make sure you have enough food and equipment to support all the troops (they consume food even when not in a battle, and insufficient equipment means lower strength). You may refer Battling for more info on soft attack/ hard attack/ other stats.
Any troops may be lost in a battle, so if you see you are getting pushed back (indicated by the decrease of attacking percentage), you should consider pulling back your troops
The following troops are available for training:
Land troops:
- Infantry
- Calvary
- Suicide bomber
- Artillery
- Logistic
- Armored car
- Tank 1
- Tank 2
- Tank oshimai (お終い)
Planes:
- Close air support
- Fighter
- Bomber
- Kamikaze
Details of each troop (1 unit):
- Infantry: camp: 1, time: 10 days, soft attack: 10, hard attack: 2, defenses: 25, speed: 5, equipment: 2, food: 2, hp: 100
- Calvary: camp: 1, time: 10 days, soft attack: 8, hard attack: 1, defenses: 20, speed: 10, equipment: 2, food: 2, hp: 150
- Suicide bomber: camp: 2, time: 50 days, soft attack: 300, hard attack: 200, defenses: 0, speed: 30, equipment: 30, food: 15, disruption: 1 (suicide bombers are a one-time use and They die immediately after dealing damage once. They ONLY deal damage when they are not taking ANY damage, meaning you must edit them into an army.), hp: N/A
- Artillery: camp: 2, time: 20 days, soft attack: 3, hard attack: 12, defenses: 10, speed: 2, equipment: 2, food: 1, hp: 170
- Logistic: camp: 1, time: 20 days, equipment: 2, defenses: 15, food: 2 (effect: increase all land troops within the same army's speed by 1 per unit and reduce food consumption by 1, including itself, max units per army: 2), hp: 50
- Armored car: camp: 2, time: 30 days, soft attack: 18, hard attack: 8, armor: 10, defenses: 30, speed: 15, equipment: 10, food: 6, hp: 160
- Tank 1: camp: 3, time: 40 days, soft attack: 12, hard attack: 20, armor: 25, defenses: 10, speed: 6, equipment: 15, food: 6, hp: 230
- Tank 2: camp: 5, time: 60 days, soft attack: 12, hard attack: 50, armor: 35, defenses: 12, speed: 8, equipment: 25, food: 8, hp: 300
- Tank oshimai: camp: 20, time: 200 days, soft attack: 80, hard attack: 150, armor: 80, defenses: 40, speed: 1, equipment: 150, food: 40, disruption: 2, hp: 1000
- Close Air Support (cas): camp: 1, time: 30 days, soft attack: 15, hard attack: 15, air attack: 2, equipment: 10, food: 2, conspicuousness: 2 (how much attack are spreaded to it), hp: 50
- Fighter: camp: 1, time: 30 days, soft attack: 4, hard attack: 2, air attack: 8, equipment: 10, food: 5, conspicuousness: 10, hp: 130
- Bomber: camp: 2, time: 45 days, soft attack: 6, hard attack: 20, disruption: 2, air attack: 2, equipment: 15, food: 3, conspicuousness: 6 , hp: 80
- Kamikaze: camp: 4, time: 70 days, soft attack: 500, hard attack: 500, disruption: 5, air attack: 150, equipment: 50, food: 20, conspicuousness: 0 (similar to suicide bombers, they will not return from battle and only deals damage once given they are not taking damage. Kamikaze does not take any damage when any other planes belonging to you are present.), hp: N/A
-
You are always encouraged to groups troops trained into army because not only can you benefit from logistics, you can also customize the layout and sustain the damage output. You can specify which troops are in front and in the back. For example, it may be useful to put tanks in the front and infantries at the back. The formation of an army is shown as below.
D1 C1 B1 A1
D2 C2 B2 A2
D3 C3 B3 A3
D4 C4 B4 A4
An army can only have a maximum of 16 troops.
When all troops are up, column A recieves 60% of all attacks while column B gets 30% and C gets the remaining 10% and D receiving none. Note the multipliers are accumulatable and in the end all 100% damage must be taken (given the presence of land troops) (Only applicable to soft attacks.)
It is important to note that within each column, how the attack is spread among the 1, 2, 3, 4 troops are completely random. There are, however, limits to how extreme the values can be (+-15%). Yet, it may still be possible for a troop to die very fast.
You may not need to occupy all the slots within the army, but say if you only put 1 troop in column A, or all except 1 troop in column A died, the remaining 1 troop will take all the 60% attack. So think carefully when editing.
Note the army name must be unique and cannot coincide with any other armies' names.
-
You can initiate a battle at any point in time by assigning armies or individual troops (for those not in an army). A battle is won once all troops on one side in the region die or if the block does not have any troops initially.
As mentioned before in Map design and coordinate system, you must start by attacking region A, then B and so on and so forth. As to what countries you want to invade first, it's entirely up to you.
You can add in more troops during a battle and withdraw the armies/ troops during the battle. You cannot, however, edit the army template during battle or retreat particular troops within the army (must retreat the entire army).
-
More details on Attacking/ Defending:
Soft attacks are dealt on all land troops, reduced to a quarter when troop has armor, affected by strength of troop, terrain and disruption.
Hard attacks are only dealt on land troops with armor (Armored cars and tanks), affected by strength of troop, terrain and disruption. If there are no armor present in the first 3 columns of the enemy army, then no troop will be take damage form the hard attacks.
Air attacks are only dealt on planes.
Defenses are how much attack a troop can take before losing hp, affected by strength of troop.
An attack is dealt by all troops to enemy and to us once each day. And all troops will recover a base 1 hp per day if hp is not full. (Affected by food supply, disruption and researches.)
Formulas for all the items:
Supplied food = base food required * (total food produced/ total base food required (capped at 1, meaning sufficient food for all troops)) In special cases when you surround 1 enemy region by occupying the 4 adjacent blocks, you cut off their supply routes and they receive 0 food no matter of their food production (see Other details and tips for more info)
Supplied equipment calculation is the same as the supplied food.
Food required = base food required - food reduction (0 reduction if not in army) Equipment required = base equipment required - requipment reduction (0 reduction if not in army)
Subsequential strength = (supplied food/ food required + supplied equipment/ equipment required)/ 2 * 100% (if no food/ equipment is required, then the caluclation will not take the average, but rather 1 fraction or 100%) (equivalent for all troops within the same army)
Pivotal strength (100% at full health, minimum ~30%, exponential, hp here = current health/ base health)
Strength of troop = Pivotal stength * 0.6 + Subsequential strength * 0.4
(From the calculation, all troops will suffer from low strength should any of the food or equipment supplied is insufficient.)
Total adjusted disruption (capped at 50%, start at 0%)
Attack debuff for different terrains (not applicable to planes):
- Plain: 0%
- Hill: 2%
- River: 4%
- Mountain: 5%
- Snowland: 8%
- Desert: 10%
Attack debuff = base value (terrain) * (1 - speed (troop)/ 10)
Air supremacy (reaches 90% when you have 1.3 times more air attack then the opponent) (100% if enemy doesn't have plane)
Normalized air supremacy effect = base value * 0.3 + 0.7 (0.0-1.0 -> 0.7-1.0)
Air attack = base value (plane) * strength
Soft attack per troop = base value (troop) * strength * (1.1 bonus damage when in full strength) * (1 - disruption) * (1 - attack debuff) * Normalized air supremacy effect
Hard attack per troop = base value (troop) * strength * (1.1 bonus damage when in full strength) * (1 - disruption/ 4) * (1 - attack debuff) * Normalized air supremacy effect
Decrease in hp from land attack per troop (non-armored) = Total soft attack / (defending armies + singly defending troops) * (column percentage (in army)) * random value from 0 to 1 (exclusive) (sums up to 1 within the same column) - defenses
Decrease in hp from land attack per troop (armored) = Decrease in hp from attack per troop (non-armored)/4 + (Total hard attack/ number of armored land troops - armor) * 1.1
Decrease in hp from air attack per troop (plane) = Total air attack * base conpicuousness/ total conpicuousness
Increase in hp from recovery per land troop = base value (research) * (1 - disruption/2) * (food supplied/ food required)^1.5
Increase in hp from recovery per air troop = base value (research) * (1 - disruption/2) * (food supplied/ food required)^1.5
(Hence if you surround an enemy region, all troops their will not be able to recover because of 0 food supply)
-
-
pause more often
The most challenging factor in this game is the time limit, becuase with sufficient time, you can beat any level as long as you can deal some damage because the enemy does not heal when not in battle. You have to carefully plan which block to attack first to reduce the casualties suffered because training new troops are time consuming, and all these thinkings are time-consuming so it is better to pause often.
-
aim for 70% captulation rate
Always go for blocks with less troops. Although many times, they have less acquirables, but the time-cost is lower because less troops will be dead, so no extra training is needed. Hence, it is often the case where you will need to aim for capturing 70% of the lands.
-
focus on development in the beginning
You maybe able to capture quite a few bits of land in the beginning. But it maybe better to be more organized and do all the buildings in the beginning and launch mass assaults later in the game. One reason is that if you have an army strong enough, you won't suffer any casualties so no extra training is needed. However, if your attack number is similar to the enemies, then you will probably lose a lot of troops even you can capture the block.
-
always put in 2 logistics in the back of an army
You can reduce food required by up to 32 which reduces the need for you to build more farms. Also, putting them in the back lowers the risk of them dying.
-
Using Suicide Bomber and Kamikaze
These 2 troops are considered special troops, and for them to give any damage output, you must have 2 times the number of non-special troops in the battlefield.
-
Air Troops Damage Output
There is a damage dropoff associated with the planes. When you do not have 3 times the number of land troops, the planes damage will start to decrease to 0.
-
Encirclement
You can encircle 1 region of the enemy troops by taking over all 4 adjacent lands, and causing the food supply to drop to 0.
For examples,
Taking over C2 in this map will encircle B2.
Taking over E6 and F7 will encircle E7.
Taking over C3, D1 and E2 will encircle D2.A1 A2 A3 B2 B4 B5 C2 C3 C4 C5 C6 C7 D1 D2 D5 E1 E2 E4 E4 E5 E6 E7 F1 F2 F7 G1 G7 H1 H2 H7
Taking over G2 in this map will encircle G1, G3 and H2 .
A1 A2 A3 B2 B4 B5 C2 C3 C4 C5 C6 C7 D1 D2 D5 E1 E2 E4 E4 E5 E6 E7 F2 F7 G1 G2 G3 G7 H2 H7
-
Level number coloring
Yellow indicates you have beaten the level in easy mode.
Green indicates syou have beaten the level in hard mode.
You can create a random levels with difficulty 1 to 5 with 1 being the easiest and 5 being the hardest. All maps and resources will be different. Time limit is 99999 days. Note, the effect of very large numbers of anything is still not tested.
-
Random elements
- in damage calculation for armies
- random levels
-
STL containers
- everywhere
-
Classes
- TroopUnit, ArmyUnit, Block, Enemy, Progress, BattleTroopWrapper, BattleUnit, Game
-
Structs
- too many to be listed
-
Dynamic memory usages
- when creating any classes ( raw pointers )
- when using stl contianers
-
Saving and Loading
- saving mid-game and loading from it
- saving the completed levels
- saving the settings
-
Multiple files
- too many to be listed
Term:
- print: printing in terminal
- new: by using dynamic memory
- phase: may contain multiple functions/actions or blocks of codes in different places
Stage 1:
Menu phase
↳ Levels ⇆ Setting data origin (level data/ random) ⇆ start Game ➜ stage 2
↳ Settings ⇆ modify settings
↳ Stats
Stage 2: Game Phase
Flow: constructor ➜ fetch ➜ start
Constructor Phase
resource
, building
, troop
, army
, research
, battle
, enemies
( all structs in namespace data )Resource: store all game stats (food, equipment, multipliers, ...) (self)
Building: store all building stats (built, upgraded, building)
Troop: store all
TroopUnit
with the number counts (trained, in battle, in army, training)Army: store all
ArmyUnit
Research: store all research stats (researched, researching)
Battle: ONLY the general status of whether in battle and is in battle with which country _for printing_
Enemies: store all
Enemy
and number of defeated enemiesFetch phase
The four main phases in
start phase
will be explained below. You may skip them if not interested.
Printing Phase
- main screen
- building screen
- research screen
- training screen
Whenever user's input changes the screen, the condition variable for that loop will be notified to quit the loop and start another new loop.
Reason why condition variable is used instead of simply sleeping the thread is that I need to be able to wake the thread from sleeping which is impossible when actually sleeping the thread. I can, however, wait and cancel waiting for condition variable.
These functions take in the arrow key position in x and y coordinate, return null.
Non-blocking: blocks
input phase
of Game until the async thread is initiated for setting up the loopingData race: lguser locked when setting up the looping, lg3 locked when printing
Action Phase
- army screen
- battle screen
- changing speed
- pausing
- restart
- quit
army screen
and battle screen
will have their own while loops for input phase
, print phase
and action phase
These functions take in the gamePhase by reference (int, which screen to print or what action to do ) and previous gamePhase, return null.
The actions should finish by setting gamePhase to previous gamePhase because the user should be sent back to his last screen.
Non-blocking: blocks
input phase
of GameData race: handled inside the actions ( some may not, not sure, and thats why the game is prone to crashing )
Input Phase
up arrow: esc, [, A
^[[A
down arrow: esc, [, B
^[[B
right arrow: esc, [, C
^[[C
left arrow: esc, [, D
^[[D
Changes gamePhase when user press any shortcut keys or enter.
When input is detected, all current printing loops will be stopped.
Not a function
Non-blocking: blocks
start phase
until user inputsData race: lguser locked when stopping the loop ( and locked when trying to start the loop later ) so data race due to user spamming is avoided
Timer Phase
day
and battles
( not the battle struct ) until game ends in an async thread.Flow: ⟲ increment day
⟲ start
battle cycle phase
⟲
regen (self)
Takes in fps and game speed in int, returns null when while loop exit.
Non-blocking: non blocking
Data race: lg locked when increasing day count, refer to
battle cycle phase
for its own data race handling
Start Phase
Timer Phase
⟲
input
➜ print/action
Nothing to be exlpained.
No parameters, returns 0 ( normal exit ) or -999 ( restart game )
Non-blocking: blocks
game
( but is technically the only function that needs to be run in game )Data race: handled inside the phases
Battle Cycle Phase
Fight
➜ Clean
➜ Regen
➜ Check End Battle
Fight: calculate all stats and damage of the battling troops
Clean: remove all troops whose health is below 0
Regen: increment all troops health Check End Battle: as the function name suggests
endGame
(reference), gameOver (reference), enemySize, troop (ptr), resource (ptr), building (ptr), battle (ptr), buildBase (reference)
Non-blocking: blocks
Data race: that block's own lg locked
endGame
no parameters and no return value
Non-blocking: blocks
Data race: locks everything
-
Compiled with:
- c++11, using g++/gcc
-
Tested on:
- academy server 11
- ubuntu 18
- vscode wsl ( ubuntu 18 )
-
Memory leaks:
None by using valgrind
valgrind ./main
-
include/lib list
-
core:
- iostream
- fstream
- cmath
- iomanip
- cstdlib
- vector
- map
- unordered_map
- utility
- functional
- algorithm
- string
- future
- mutex
- thread (compiled with -pthread)
- condition_variable
- chrono
- iterator
- tuple
- new
- cassert (development purpose)
- termios (linux only)
- dirent.h (linux only)
-
external:
- uuid by sole (used to generate unique uuid)
-