diff --git a/ASCII-G.vcxproj b/ASCII-G.vcxproj
index 23bb508..a433f61 100644
--- a/ASCII-G.vcxproj
+++ b/ASCII-G.vcxproj
@@ -1,4 +1,4 @@
-
+
@@ -123,6 +123,7 @@
+
@@ -130,6 +131,7 @@
+
diff --git a/ASCII-G.vcxproj.filters b/ASCII-G.vcxproj.filters
index 0b563bd..52d2269 100644
--- a/ASCII-G.vcxproj.filters
+++ b/ASCII-G.vcxproj.filters
@@ -24,13 +24,19 @@
Исходные файлы
+
+ Исходные файлы
+
+
+ Файлы заголовков
+
- Исходные файлы
+ Файлы заголовков
- Исходные файлы
+ Файлы заголовков
\ No newline at end of file
diff --git a/data/locations/location_1.txt b/data/locations/location_1.txt
new file mode 100644
index 0000000..26a2980
--- /dev/null
+++ b/data/locations/location_1.txt
@@ -0,0 +1,21 @@
+ID=1
+TITLE=Entrance Hall
+WIDTH=10
+HEIGHT=6
+START_X=1
+START_Y=1
+NORTH=0
+SOUTH=2
+WEST=0
+EAST=0
+RIDDLE_TYPE=1
+RIDDLE_TEXT=What gets bigger when you take something away?
+RIDDLE_ANSWER=hole
+MAP_BEGIN
+##########
+#@.......#
+#....C...#
+#........#
+#......D.#
+##########
+MAP_END
\ No newline at end of file
diff --git a/data/locations/location_2.txt b/data/locations/location_2.txt
new file mode 100644
index 0000000..d6b500a
--- /dev/null
+++ b/data/locations/location_2.txt
@@ -0,0 +1,21 @@
+ID=2
+TITLE=Old Corridor
+WIDTH=10
+HEIGHT=6
+START_X=1
+START_Y=1
+NORTH=1
+SOUTH=3
+WEST=0
+EAST=0
+RIDDLE_TYPE=2
+RIDDLE_TEXT=Decode this word: MBHJD. Each letter is shifted by one.
+RIDDLE_ANSWER=magic
+MAP_BEGIN
+##########
+#@.......#
+#..E.....#
+#........#
+#......D.#
+##########
+MAP_END
\ No newline at end of file
diff --git a/data/locations/location_3.txt b/data/locations/location_3.txt
new file mode 100644
index 0000000..1bae725
--- /dev/null
+++ b/data/locations/location_3.txt
@@ -0,0 +1,21 @@
+ID=3
+TITLE=Guard Room
+WIDTH=10
+HEIGHT=6
+START_X=1
+START_Y=1
+NORTH=2
+SOUTH=4
+WEST=0
+EAST=0
+RIDDLE_TYPE=3
+RIDDLE_TEXT=Continue the sequence: 2 4 8 16
+RIDDLE_ANSWER=32
+MAP_BEGIN
+##########
+#@.......#
+#....N...#
+#........#
+#......D.#
+##########
+MAP_END
\ No newline at end of file
diff --git a/data/locations/location_4.txt b/data/locations/location_4.txt
new file mode 100644
index 0000000..aca674e
--- /dev/null
+++ b/data/locations/location_4.txt
@@ -0,0 +1,21 @@
+ID=4
+TITLE=Library
+WIDTH=10
+HEIGHT=6
+START_X=1
+START_Y=1
+NORTH=3
+SOUTH=5
+WEST=0
+EAST=0
+RIDDLE_TYPE=4
+RIDDLE_TEXT=Where is knowledge usually stored?
+RIDDLE_ANSWER=book
+MAP_BEGIN
+##########
+#@.......#
+#....C...#
+#..E.....#
+#......D.#
+##########
+MAP_END
\ No newline at end of file
diff --git a/data/locations/location_5.txt b/data/locations/location_5.txt
new file mode 100644
index 0000000..471f11d
--- /dev/null
+++ b/data/locations/location_5.txt
@@ -0,0 +1,21 @@
+ID=5
+TITLE=Final Gate
+WIDTH=10
+HEIGHT=6
+START_X=1
+START_Y=1
+NORTH=4
+SOUTH=0
+WEST=0
+EAST=0
+RIDDLE_TYPE=5
+RIDDLE_TEXT=What key opens no door?
+RIDDLE_ANSWER=keyboard
+MAP_BEGIN
+##########
+#@.......#
+#....E...#
+#....C...#
+#......D.#
+##########
+MAP_END
\ No newline at end of file
diff --git a/include/game.h b/include/game.h
index 3021646..609eac8 100644
--- a/include/game.h
+++ b/include/game.h
@@ -1,5 +1,7 @@
-#include "player.h"
#pragma once
+#include "player.h"
+#include "location.h"
+#include
class Game {
public:
@@ -7,11 +9,20 @@ public:
private:
bool isRunning = true;
+
Player player;
+ std::vector locations;
void showMainMenu();
- void processCommand();
- void render();
-};
-#pragma once
+ void loadLocations();
+ Location* getCurrentLocation();
+
+ void render();
+ void processCommand();
+
+ void movePlayer(int dx, int dy);
+ void handleTile(char tile);
+
+ bool solveRiddle(Location& location);
+};
\ No newline at end of file
diff --git a/include/location.h b/include/location.h
new file mode 100644
index 0000000..e2c9f4e
--- /dev/null
+++ b/include/location.h
@@ -0,0 +1,61 @@
+#pragma once
+#include
+#include
+
+struct Point {
+ int x = 0;
+ int y = 0;
+};
+
+struct Chest {
+ Point pos;
+ int gold = 0;
+ bool opened = false;
+};
+
+struct Enemy {
+ Point pos;
+ std::string type;
+ int hp = 50;
+};
+
+struct NPC {
+ Point pos;
+ std::string name;
+};
+
+struct Riddle {
+ int type = 0;
+ std::string text;
+ std::string answer;
+ bool isSolved = false;
+};
+
+class Location {
+public:
+ int id = 0;
+ std::string title;
+
+ int width = 0;
+ int height = 0;
+
+ int north = 0;
+ int south = 0;
+ int west = 0;
+ int east = 0;
+
+ Point startPosition;
+ Riddle riddle;
+
+ std::vector map;
+ std::vector chests;
+ std::vector enemies;
+ std::vector npcs;
+
+ bool loadFromFile(const std::string& path);
+
+ void draw(const Point& playerPosition) const;
+
+ bool isWalkable(int x, int y) const;
+ char getTile(int x, int y) const;
+};
\ No newline at end of file
diff --git a/include/player.h b/include/player.h
index ca7350c..15f23ec 100644
--- a/include/player.h
+++ b/include/player.h
@@ -1,20 +1,24 @@
#pragma once
#include
#include
+#include "location.h"
class Player {
public:
std::string name = "Character Name";
+
int hp = 100;
- int atk = 1;
+ int atk = 10;
int gold = 0;
+
int currentLocation = 1;
+ Point position;
+
int weaponId = 101;
std::vector items;
- Player() {};
- Player(std::string _name);
- void showStats();
-};
+ Player() = default;
+ Player(std::string name);
-#pragma once
+ void showStats() const;
+};
\ No newline at end of file
diff --git a/location.cpp b/location.cpp
deleted file mode 100644
index e69de29..0000000
diff --git a/location.h b/location.h
deleted file mode 100644
index 49a3aa9..0000000
--- a/location.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-#include
-
-class Location {
-public:
- std::string title;
- int id;
- int sizeX;
- int sizeY;
- int gold = 0;
-
- Location() {};
- Location(std::string _name);
- void showStats();
-};
-
-#pragma once
diff --git a/src/game.cpp b/src/game.cpp
index 9750835..4d907a4 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1,16 +1,40 @@
#include "../include/game.h"
-#include "../include/player.h"
#include
#include
void Game::run() {
+ loadLocations();
showMainMenu();
+
while (isRunning) {
render();
processCommand();
}
}
+void Game::loadLocations() {
+ locations.clear();
+
+ for (int i = 1; i <= 5; i++) {
+ Location location;
+ std::string path = "data/locations/location_" + std::to_string(i) + ".txt";
+
+ if (location.loadFromFile(path)) {
+ locations.push_back(location);
+ }
+ }
+}
+
+Location* Game::getCurrentLocation() {
+ for (auto& location : locations) {
+ if (location.id == player.currentLocation) {
+ return &location;
+ }
+ }
+
+ return nullptr;
+}
+
void Game::showMainMenu() {
while (true) {
std::cout << "=== ASCII-G - The Cookies Edition ===\n";
@@ -22,47 +46,61 @@ void Game::showMainMenu() {
std::string str;
std::getline(std::cin, str);
- if (str.length() != 1) {
- std::cout << "It seems you've tried to input more than 1 digit... Don't do this please.\n";
- continue;
- }
-
- char select = str[0];
-
- if (select == '1') {
+ if (str == "1") {
std::string name;
+
std::cout << ">>> Enter your character name: ";
std::getline(std::cin, name);
- if (name == "") {
- std::cout << ">>> Empty name? Damn... let's call you Zero!\n";
+
+ if (name.empty()) {
player = Player("Zero");
}
else {
player = Player(name);
}
- std::cout << ">>> Created new character " << player.name << "!";
+
+ Location* location = getCurrentLocation();
+
+ if (location != nullptr) {
+ player.position = location->startPosition;
+ }
+
+ std::cout << ">>> Created new character " << player.name << "!\n";
break;
}
- else if (select == '2') {
- std::cout << ">>> I can't do this... yet.";
+ else if (str == "2") {
+ std::cout << ">>> Load system is not ready yet.\n";
}
- else if (select == '3') {
+ else if (str == "3") {
isRunning = false;
break;
}
else {
- std::cout << ">>> I can't do this... yet? Let's try again!";
+ std::cout << ">>> Unknown menu option.\n";
}
}
}
void Game::render() {
- std::cout << "\n\n=== ASCII-G - The Cookies Edition ===\n";
- std::cout << "Commands: stats, exit\n";
+ Location* location = getCurrentLocation();
+
+ if (location == nullptr) {
+ std::cout << "Current location not found.\n";
+ isRunning = false;
+ return;
+ }
+
+ location->draw(player.position);
+
+ std::cout << "\nCommands:\n";
+ std::cout << "WASD - move\n";
+ std::cout << "stats - show stats\n";
+ std::cout << "exit - exit game\n";
}
void Game::processCommand() {
std::string command;
+
std::cout << "> ";
std::cin >> command;
@@ -72,7 +110,117 @@ void Game::processCommand() {
else if (command == "stats") {
player.showStats();
}
+ else if (command == "w" || command == "W") {
+ movePlayer(0, -1);
+ }
+ else if (command == "s" || command == "S") {
+ movePlayer(0, 1);
+ }
+ else if (command == "a" || command == "A") {
+ movePlayer(-1, 0);
+ }
+ else if (command == "d" || command == "D") {
+ movePlayer(1, 0);
+ }
else {
std::cout << "Unknown command.\n";
}
+}
+
+void Game::movePlayer(int dx, int dy) {
+ Location* location = getCurrentLocation();
+
+ if (location == nullptr) {
+ return;
+ }
+
+ int newX = player.position.x + dx;
+ int newY = player.position.y + dy;
+
+ if (!location->isWalkable(newX, newY)) {
+ std::cout << "You hit the wall.\n";
+ return;
+ }
+
+ char tile = location->getTile(newX, newY);
+
+ player.position.x = newX;
+ player.position.y = newY;
+
+ handleTile(tile);
+}
+
+void Game::handleTile(char tile) {
+ Location* location = getCurrentLocation();
+
+ if (location == nullptr) {
+ return;
+ }
+
+ if (tile == 'C') {
+ std::cout << "You found a chest. For now it gives you 25 gold.\n";
+ player.gold += 25;
+ }
+ else if (tile == 'E') {
+ std::cout << "Enemy encountered. Combat will be added later.\n";
+ }
+ else if (tile == 'N') {
+ std::cout << "NPC: Hello, traveler.\n";
+ }
+ else if (tile == 'D') {
+ if (!location->riddle.isSolved) {
+ bool solved = solveRiddle(*location);
+
+ if (!solved) {
+ player.hp -= 10;
+ std::cout << "Wrong answer. You lost 10 HP.\n";
+ return;
+ }
+ }
+
+ if (location->south != 0) {
+ player.currentLocation = location->south;
+ }
+ else if (location->east != 0) {
+ player.currentLocation = location->east;
+ }
+ else if (location->north != 0) {
+ player.currentLocation = location->north;
+ }
+ else if (location->west != 0) {
+ player.currentLocation = location->west;
+ }
+ else {
+ std::cout << "There is no exit from this door.\n";
+ return;
+ }
+
+ Location* newLocation = getCurrentLocation();
+
+ if (newLocation != nullptr) {
+ player.position = newLocation->startPosition;
+ std::cout << "You entered: " << newLocation->title << "\n";
+ }
+ }
+}
+
+bool Game::solveRiddle(Location& location) {
+ if (location.riddle.text.empty()) {
+ return true;
+ }
+
+ std::cout << "\nRiddle:\n";
+ std::cout << location.riddle.text << "\n";
+ std::cout << "Answer: ";
+
+ std::string answer;
+ std::cin >> answer;
+
+ if (answer == location.riddle.answer) {
+ std::cout << "Correct.\n";
+ location.riddle.isSolved = true;
+ return true;
+ }
+
+ return false;
}
\ No newline at end of file
diff --git a/src/location.cpp b/src/location.cpp
new file mode 100644
index 0000000..b468753
--- /dev/null
+++ b/src/location.cpp
@@ -0,0 +1,127 @@
+#include "../include/location.h"
+#include
+#include
+#include
+
+bool Location::loadFromFile(const std::string& path) {
+ std::ifstream file(path);
+
+ if (!file.is_open()) {
+ std::cout << "Cannot open location file: " << path << "\n";
+ return false;
+ }
+
+ std::string line;
+ bool readingMap = false;
+
+ while (std::getline(file, line)) {
+ if (line.empty()) {
+ continue;
+ }
+
+ if (line == "MAP_BEGIN") {
+ readingMap = true;
+ continue;
+ }
+
+ if (line == "MAP_END") {
+ readingMap = false;
+ continue;
+ }
+
+ if (readingMap) {
+ map.push_back(line);
+ continue;
+ }
+
+ size_t pos = line.find('=');
+ if (pos == std::string::npos) {
+ continue;
+ }
+
+ std::string key = line.substr(0, pos);
+ std::string value = line.substr(pos + 1);
+
+ if (key == "ID") id = std::stoi(value);
+ else if (key == "TITLE") title = value;
+ else if (key == "WIDTH") width = std::stoi(value);
+ else if (key == "HEIGHT") height = std::stoi(value);
+ else if (key == "START_X") startPosition.x = std::stoi(value);
+ else if (key == "START_Y") startPosition.y = std::stoi(value);
+ else if (key == "NORTH") north = std::stoi(value);
+ else if (key == "SOUTH") south = std::stoi(value);
+ else if (key == "WEST") west = std::stoi(value);
+ else if (key == "EAST") east = std::stoi(value);
+ else if (key == "RIDDLE_TYPE") riddle.type = std::stoi(value);
+ else if (key == "RIDDLE_TEXT") riddle.text = value;
+ else if (key == "RIDDLE_ANSWER") riddle.answer = value;
+ }
+
+ for (int y = 0; y < map.size(); y++) {
+ for (int x = 0; x < map[y].size(); x++) {
+ char tile = map[y][x];
+
+ if (tile == 'C') {
+ Chest chest;
+ chest.pos = { x, y };
+ chest.gold = 25;
+ chests.push_back(chest);
+ }
+ else if (tile == 'E') {
+ Enemy enemy;
+ enemy.pos = { x, y };
+ enemy.type = "Goblin";
+ enemy.hp = 50;
+ enemies.push_back(enemy);
+ }
+ else if (tile == 'N') {
+ NPC npc;
+ npc.pos = { x, y };
+ npc.name = "Stranger";
+ npcs.push_back(npc);
+ }
+ }
+ }
+
+ return true;
+}
+
+void Location::draw(const Point& playerPosition) const {
+ std::cout << "\n=== " << title << " ===\n";
+
+ for (int y = 0; y < map.size(); y++) {
+ for (int x = 0; x < map[y].size(); x++) {
+ if (playerPosition.x == x && playerPosition.y == y) {
+ std::cout << '@';
+ }
+ else {
+ char tile = map[y][x];
+
+ if (tile == '@') {
+ std::cout << '.';
+ }
+ else {
+ std::cout << tile;
+ }
+ }
+ }
+
+ std::cout << "\n";
+ }
+}
+
+bool Location::isWalkable(int x, int y) const {
+ if (y < 0 || y >= map.size()) return false;
+ if (x < 0 || x >= map[y].size()) return false;
+
+ char tile = map[y][x];
+
+ return tile != '#';
+}
+
+char Location::getTile(int x, int y) const {
+ if (y < 0 || y >= map.size()) return '#';
+ if (x < 0 || x >= map[y].size()) return '#';
+
+ return map[y][x];
+}
\ No newline at end of file
diff --git a/src/player.cpp b/src/player.cpp
index 8c360d8..f07fef3 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -1,17 +1,19 @@
#include "../include/player.h"
#include
-Player::Player(std::string _name)
-{
- this->name = _name;
+Player::Player(std::string name) {
+ this->name = name;
hp = 100;
atk = 10;
gold = 0;
+ currentLocation = 1;
}
-void Player::showStats() {
- std::cout << "\n === " << this->name << "'s STATS ===";
- std::cout << "\nHP : " << this->hp;
- std::cout << "\nATK : " << this->atk;
- std::cout << "\nGOLD : " << this->gold;
+void Player::showStats() const {
+ std::cout << "\n=== " << name << "'s STATS ===";
+ std::cout << "\nHP: " << hp;
+ std::cout << "\nATK: " << atk;
+ std::cout << "\nGOLD: " << gold;
+ std::cout << "\nLOCATION: " << currentLocation;
+ std::cout << "\nPOSITION: " << position.x << ", " << position.y << "\n";
}
\ No newline at end of file