Projet Primark
Structure Initiale en C++ avec programiz.pro
simulation.cpp
#include
#include
#include
using namespace std;
// Classe pour les ressources
class Resource {
public:
string type; // "bois", "pierre", etc.
int x, y; // Position sur la grille
int quantity; // Quantité restante
Resource(string t, int px, int py, int q) : type(t), x(px), y(py), quantity(q) {}
};
// Classe pour les personnages
class Character {
public:
string name;
int x, y; // Position
string role; // "mineur", "soldat", etc.
int energy; // Énergie (dormir pour récupérer)
string personality; // Ex. : "paresseux", "courageux"
bool controlled; // Est-ce que le dieu le contrôle ?
Character(string n, int px, int py, string r, string p)
: name(n), x(px), y(py), role(r), energy(100), personality(p), controlled(false) {}
void move(int newX, int newY) {
x = newX;
y = newY;
energy -= 10; // Déplacement coûte de l'énergie
}
void collect(Resource& res) {
if (res.quantity > 0) {
res.quantity--;
cout << name << " a collecté 1 " << res.type << endl;
}
}
};
// Classe pour le dieu
class God {
public:
Character* controlledCharacter = nullptr;
void takeControl(Character& c) {
if (!c.controlled) {
controlledCharacter = &c;
c.controlled = true;
cout << "Dieu prend le contrôle de " << c.name << endl;
}
}
void releaseControl() {
if (controlledCharacter) {
controlledCharacter->controlled = false;
cout << "Dieu relâche " << controlledCharacter->name << endl;
controlledCharacter = nullptr;
}
}
void changeRole(string newRole) {
if (controlledCharacter) {
controlledCharacter->role = newRole;
cout << controlledCharacter->name << " devient " << newRole << endl;
}
}
};
// Classe pour le monde
class World {
public:
vector characters;
vector resources;
int width, height; // Taille de la grille
World(int w, int h) : width(w), height(h) {}
void addCharacter(Character c) { characters.push_back(c); }
void addResource(Resource r) { resources.push_back(r); }
void update() {
for (auto& c : characters) {
if (!c.controlled) {
// Comportement autonome simple
cout << c.name << " agit seul en tant que " << c.role << endl;
}
}
}
};
int main() {
World world(20, 20); // Grille 20x20
God god;
// Ajouter des personnages et ressources
world.addCharacter(Character("Primak1", 5, 5, "mineur", "travailleur"));
world.addCharacter(Character("Primak2", 6, 6, "mineur", "paresseux"));
world.addResource(Resource("bois", 10, 10, 5));
// Simulation simple
god.takeControl(world.characters[0]);
god.changeRole("soldat");
world.characters[0].move(7, 7);
god.releaseControl();
world.update();
return 0;
}
Migration vers Visual Studio
Configuration Initiale Migration vers Visual Studio
- VS Code 1.98.2
- C/C++ for Visual Studio Code version 1.23.6
- Software Distribution and Building Platform for Windows https://www.msys2.org/ msys2-x86_64-20250221.exe
- “miDebuggerPath”: “C:\\msys64\\ucrt64\\bin\\gdb.exe”
Dossier du projet
- PrimakSim
- .vscode
- launch.json
- setting.json
- tasks.json
- simulation.cpp
- simulation.exe
- .vscode
Version fonctionnelle 2.1.1
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "C:\\msys64\\ucrt64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build active file"
}
]
}
settings.json
{
"files.associations": {
"iostream": "cpp"
}
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "g++",
"args": [
"-g",
"-march=x86-64", // Ajoute ce flag pour spécifier l'architecture
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
simulation.cpp
// Version 2.1.1
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef _WIN32
#include // For detecting CMD and enabling ANSI support
#endif
using namespace std;
// ANSI color codes for highlighting
#define YELLOW_BG_BLACK_TEXT "\033[43;30m"
#define RESET_COLOR "\033[0m"
// Class Resource
class Resource {
public:
string type;
int x, y;
int quantity;
Resource(string t, int px, int py, int q) : type(t), x(px), y(py), quantity(q) {}
};
// Class Stockpile
class Stockpile {
public:
int x, y;
int wood;
Stockpile(int px, int py) : x(px), y(py), wood(0) {}
};
// Class Building
class Building {
public:
string type;
int x, y;
int occupancy; // Track how many Primak are using this building
Building(string t, int px, int py) : type(t), x(px), y(py), occupancy(0) {}
};
// Class to store logs for CSV export
class LogEntry {
public:
int day, hour;
string name, action;
int energy, hunger, wood, food, gestation, x, y;
LogEntry(int d, int h, string n, int e, int hu, int w, int f, int g, int px, int py, string a = "")
: day(d), hour(h), name(n), energy(e), hunger(hu), wood(w), food(f), gestation(g), x(px), y(py), action(a) {}
};
// Class Character
class Character {
public:
string name;
int x, y;
string role;
int energy;
int hunger;
int wood;
int food;
string personality;
bool controlled;
bool alive;
string gender;
int gestation;
int procreationCooldown;
Character(string n, int px, int py, string r, string p, string g)
: name(n), x(px), y(py), role(r), energy(100), hunger(0), wood(0), food(0), personality(p), controlled(false), alive(true), gender(g), gestation(0), procreationCooldown(0) {}
void move(int newX, int newY) {
int energyCost = (gender == "femme") ? 12 : 8;
if (energy >= energyCost) {
x = newX;
y = newY;
energy -= energyCost;
hunger += (gender == "homme") ? 2 : 3;
}
}
void collect(Resource& res) {
int energyCost = (gender == "femme") ? 10 : 5;
if (energy >= energyCost && res.quantity > 0) {
res.quantity--;
energy -= energyCost;
hunger += (gender == "homme") ? 2 : 3;
if (res.type == "bois") wood++;
else if (res.type == "nourriture") food++;
}
}
void eat(Building* cantine = nullptr) {
if (cantine && cantine->type == "cantine" && x == cantine->x && y == cantine->y) {
hunger = max(0, hunger - 70);
cantine->occupancy++;
cout << name << " eats at the canteen and reduces hunger to " << hunger << endl;
} else if (food > 0) {
food--;
hunger = max(0, hunger - 30);
}
}
void deposit(Stockpile& stock) {
if (wood > 0 && x == stock.x && y == stock.y) {
stock.wood += wood;
cout << name << " deposits " << wood << " wood in the stockpile (total: " << stock.wood << ")" << endl;
wood = 0;
}
}
void sleep(Building* building = nullptr) {
if (building && building->type == "maison" && x == building->x && y == building->y) {
energy = min(100, energy + 30);
hunger = max(0, hunger - 50);
building->occupancy++;
cout << name << " sleeps in the house and recovers energy (" << energy << ") and hunger (" << hunger << ")" << endl;
} else if (building && building->type == "hotel" && x == building->x && y == building->y) {
energy = min(100, energy + 30);
building->occupancy++;
cout << name << " sleeps in the hotel and recovers energy (" << energy << ")" << endl;
} else {
energy = min(100, energy + 10);
}
hunger += (gender == "homme") ? 1 : 2;
}
void tryProcreate(vector& characters) {
if (gender == "femme" && gestation == 0 && procreationCooldown == 0 && energy >= 30 && hunger <= 70) {
for (auto& other : characters) {
if (&other != this && other.gender == "homme" && other.alive && !other.controlled && abs(x - other.x) <= 2 && abs(y - other.y) <= 2 && other.energy >= 30 && other.hunger <= 70) {
gestation = 24;
cout << name << " and " << other.name << " will have a child in 24h!" << endl;
break;
}
}
}
if (procreationCooldown > 0) procreationCooldown--;
}
};
// Class God
class God {
public:
Character* controlledCharacter = nullptr;
void takeControl(Character& c) {
if (!c.controlled && c.alive) {
controlledCharacter = &c;
c.controlled = true;
cout << "God takes control of " << c.name << endl;
}
}
void releaseControl() {
if (controlledCharacter) {
controlledCharacter->controlled = false;
cout << "God releases " << controlledCharacter->name << endl;
controlledCharacter = nullptr;
}
}
void changeRole(string newRole) {
if (controlledCharacter) {
controlledCharacter->role = newRole;
cout << controlledCharacter->name << " becomes " << newRole << endl;
}
}
};
// Class World
class World {
public:
vector characters;
vector resources;
vector stockpiles;
vector buildings;
vector logs;
int width, height;
int time;
int day;
string season;
int nextPrimakId;
bool useAnsiColors; // Flag to enable/disable ANSI colors
World(int w, int h) : width(w), height(h), time(0), day(1), season("printemps"), nextPrimakId(1) {
srand(static_cast(std::time(nullptr)));
// Check if ANSI colors are supported (disable in CMD)
#ifdef _WIN32
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD consoleMode;
useAnsiColors = GetConsoleMode(hConsole, &consoleMode);
if (useAnsiColors) {
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole, consoleMode);
}
#else
useAnsiColors = true; // Assume ANSI support on non-Windows systems
#endif
}
void addCharacter(Character c) {
c.name = "Primak" + to_string(nextPrimakId++);
characters.push_back(c);
}
void addResource(Resource r) { resources.push_back(r); }
void addStockpile(Stockpile s) { stockpiles.push_back(s); }
void addBuilding(Building b) { buildings.push_back(b); }
void display() {
if (useAnsiColors) {
cout << YELLOW_BG_BLACK_TEXT << "Day " << day << " - Hour " << time << "h (" << season << ")" << RESET_COLOR << "\n";
} else {
cout << "Day " << day << " - Hour " << time << "h (" << season << ")\n";
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
bool printed = false;
for (auto& c : characters) {
if (c.x == x && c.y == y && c.alive) {
cout << (c.gender == "homme" ? "H" : "F");
printed = true;
break;
}
}
if (!printed) {
for (auto& b : buildings) {
if (b.x == x && b.y == y) {
if (b.type == "maison") cout << "M";
else if (b.type == "cantine") cout << "C";
else if (b.type == "hotel") cout << "O";
printed = true;
break;
}
}
}
if (!printed) {
for (auto& s : stockpiles) {
if (s.x == x && s.y == y) {
cout << "S";
printed = true;
break;
}
}
}
if (!printed) {
for (auto& r : resources) {
if (r.x == x && r.y == y && r.quantity > 0) {
cout << (r.type == "bois" ? "B" : "N");
printed = true;
break;
}
}
}
if (!printed) cout << ".";
}
cout << endl;
}
if (time % 6 == 0) {
cout << "Primak Stats:\n";
cout << left << setw(10) << "Name" << setw(10) << "Energy" << setw(10) << "Hunger" << setw(10) << "Wood" << setw(10) << "Food" << setw(15) << "Gestation" << "Position\n";
cout << string(65, '-') << endl;
for (const auto& c : characters) {
if (c.alive) {
cout << left << setw(10) << c.name << setw(10) << c.energy << setw(10) << c.hunger << setw(10) << c.wood << setw(10) << c.food << setw(15) << c.gestation << "(" << c.x << "," << c.y << ")\n";
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y));
}
}
cout << endl;
}
}
void update() {
vector newCharacters;
vector houseOccupancy(buildings.size(), 0);
vector hotelOccupancy(buildings.size(), 0);
vector canteenOccupancy(buildings.size(), 0);
// Reset occupancy for this update cycle
for (auto& b : buildings) {
b.occupancy = 0;
}
for (auto& c : characters) {
if (c.alive && !c.controlled) {
if (time >= 20 || time < 8 || c.energy <= 20) {
Building* target = nullptr;
int targetDist = width + height;
int targetIndex = -1;
for (size_t i = 0; i < buildings.size(); ++i) {
auto& b = buildings[i];
int dist = abs(c.x - b.x) + abs(c.y - b.y);
if (b.type == "maison" && houseOccupancy[i] < 2) {
if (dist < targetDist) {
target = &b;
targetDist = dist;
targetIndex = i;
}
} else if (b.type == "hotel" && hotelOccupancy[i] < 10) {
if (dist < targetDist) {
target = &b;
targetDist = dist;
targetIndex = i;
}
}
}
if (target && targetDist > 0 && c.energy > 20) {
int newX = c.x + (c.x < target->x ? 1 : c.x > target->x ? -1 : 0);
int newY = c.y + (c.y < target->y ? 1 : c.y > target->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to (" + to_string(newX) + "," + to_string(newY) + ")"));
} else {
if (target && target->type == "maison" && targetIndex != -1) {
houseOccupancy[targetIndex]++;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Sleep in house"));
c.sleep(target);
} else if (target && target->type == "hotel" && targetIndex != -1) {
hotelOccupancy[targetIndex]++;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Sleep in hotel"));
c.sleep(target);
} else {
c.sleep();
}
}
} else if (time >= 8 && time < 20 && c.energy > 20) {
int closestDist = width + height;
Resource* closestRes = nullptr;
Stockpile* closestStock = nullptr;
Building* closestCantine = nullptr;
int canteenIndex = -1;
if (c.wood >= 2 || (c.wood > 0 && c.hunger >= 40)) { // Reduced threshold from 50 to 40
for (auto& s : stockpiles) {
int dist = abs(c.x - s.x) + abs(c.y - s.y);
if (dist < closestDist) {
closestDist = dist;
closestStock = &s;
closestRes = nullptr;
closestCantine = nullptr;
}
}
} else {
for (auto& r : resources) {
if (r.quantity > 0) {
int dist = abs(c.x - r.x) + abs(c.y - r.y);
if (dist < closestDist && (r.type == "nourriture" || (r.type == "bois" && c.food > 0 && c.hunger < 40))) {
closestDist = dist;
closestRes = &r;
closestStock = nullptr;
closestCantine = nullptr;
}
}
}
for (auto& s : stockpiles) {
if (c.food > 0 && rand() % 10 < 8) {
int dist = abs(c.x - s.x) + abs(c.y - s.y);
if (dist < closestDist) {
closestDist = dist;
closestStock = &s;
closestRes = nullptr;
closestCantine = nullptr;
}
}
}
for (size_t i = 0; i < buildings.size(); ++i) {
auto& b = buildings[i];
if (b.type == "cantine" && c.hunger >= 40 && canteenOccupancy[i] < 10) { // Reduced threshold from 50 to 40
int dist = abs(c.x - b.x) + abs(c.y - b.y);
if (dist < closestDist) {
closestDist = dist;
closestCantine = &b;
closestRes = nullptr;
closestStock = nullptr;
canteenIndex = i;
}
}
}
}
if (closestCantine && closestDist > 0) {
int newX = c.x + (c.x < closestCantine->x ? 1 : c.x > closestCantine->x ? -1 : 0);
int newY = c.y + (c.y < closestCantine->y ? 1 : c.y > closestCantine->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to canteen (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestCantine) {
canteenOccupancy[canteenIndex]++;
c.eat(closestCantine);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Eat at canteen"));
} else if (c.hunger >= 40 && c.food > 0) { // Reduced threshold from 50 to 40
c.eat();
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Eat food"));
} else if (closestStock && closestDist > 0) {
int newX = c.x + (c.x < closestStock->x ? 1 : c.x > closestStock->x ? -1 : 0);
int newY = c.y + (c.y < closestStock->y ? 1 : c.y > closestStock->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to stockpile (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestStock) {
c.deposit(*closestStock);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Deposit wood"));
} else if (closestRes && closestDist > 0) {
int newX = c.x + (c.x < closestRes->x ? 1 : c.x > closestRes->x ? -1 : 0);
int newY = c.y + (c.y < closestRes->y ? 1 : c.y > closestRes->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to resource (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestRes) {
c.collect(*closestRes);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Collect resource"));
}
if (time >= 8 && time < 20) c.tryProcreate(characters);
}
c.hunger += (c.gender == "homme") ? 1 : 2;
if (c.hunger >= 100) {
c.energy -= 10;
if (c.energy <= 0) {
c.alive = false;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Died of hunger"));
}
}
if (c.gestation > 0) {
c.gestation--;
if (c.gestation == 0) {
string newName = "Primak" + to_string(nextPrimakId++);
newCharacters.push_back(Character(newName, c.x, c.y, "mineur", "nouveau", (rand() % 2) ? "homme" : "femme"));
c.procreationCooldown = 24;
cout << c.name << " has given birth to a new Primak!" << endl;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Give birth"));
}
}
}
}
for (auto& newChar : newCharacters) {
characters.push_back(newChar);
}
// Check if we need to build new buildings
bool needNewHouse = false, needNewCanteen = false, needNewHotel = false;
for (size_t i = 0; i < buildings.size(); ++i) {
if (buildings[i].type == "maison" && houseOccupancy[i] >= 2) needNewHouse = true;
if (buildings[i].type == "cantine" && canteenOccupancy[i] >= 10) needNewCanteen = true;
if (buildings[i].type == "hotel" && hotelOccupancy[i] >= 10) needNewHotel = true;
}
for (auto& s : stockpiles) {
if (s.wood >= 3) {
if (buildings.empty()) {
s.wood -= 3;
buildings.push_back(Building("maison", 7, 6));
cout << "A house has been built at (7,6) with 3 wood from the stockpile!" << endl;
} else if (buildings.size() == 1 && s.wood >= 3) {
s.wood -= 3;
buildings.push_back(Building("cantine", 8, 7));
cout << "A canteen has been built at (8,7) with 3 wood from the stockpile!" << endl;
} else if (buildings.size() == 2 && s.wood >= 3) {
s.wood -= 3;
buildings.push_back(Building("hotel", 8, 8));
cout << "A hotel has been built at (8,8) with 3 wood from the stockpile!" << endl;
} else if (needNewHouse && s.wood >= 3) {
s.wood -= 3;
int newX = 7 + (buildings.size() % 3); // Simple position adjustment
int newY = 6 + (buildings.size() % 3);
buildings.push_back(Building("maison", newX, newY));
cout << "A new house has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
needNewHouse = false;
} else if (needNewCanteen && s.wood >= 3) {
s.wood -= 3;
int newX = 8 + (buildings.size() % 3);
int newY = 7 + (buildings.size() % 3);
buildings.push_back(Building("cantine", newX, newY));
cout << "A new canteen has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
needNewCanteen = false;
} else if (needNewHotel && s.wood >= 3) {
s.wood -= 3;
int newX = 8 + (buildings.size() % 3);
int newY = 8 + (buildings.size() % 3);
buildings.push_back(Building("hotel", newX, newY));
cout << "A new hotel has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
needNewHotel = false;
}
}
}
time++;
if (time >= 24) {
time = 0;
day++;
if (day % 91 == 0) {
if (season == "printemps") season = "ete";
else if (season == "ete") season = "automne";
else if (season == "automne") season = "hiver";
else if (season == "hiver") season = "printemps";
}
}
}
void exportLogsToCSV() {
ofstream file("simulation_logs.csv");
file << "Day,Hour,Name,Energy,Hunger,Wood,Food,Gestation,X,Y,Action\n";
for (const auto& log : logs) {
file << log.day << "," << log.hour << "," << log.name << "," << log.energy << "," << log.hunger << ","
<< log.wood << "," << log.food << "," << log.gestation << "," << log.x << "," << log.y << ","
<< "\"" << log.action << "\"" << "\n";
}
file.close();
cout << "Logs exported to simulation_logs.csv\n";
}
};
// Command interface
void processCommand(God& god, World& world, string command) {
stringstream ss(command);
string action;
ss >> action;
if (action == "control") {
int index;
ss >> index;
if (index >= 0 && index < world.characters.size()) {
god.takeControl(world.characters[index]);
}
} else if (action == "release") {
god.releaseControl();
} else if (action == "role") {
string newRole;
ss >> newRole;
god.changeRole(newRole);
} else if (action == "move") {
int x, y;
ss >> x >> y;
if (god.controlledCharacter) {
god.controlledCharacter->move(x, y);
}
}
}
int main() {
bool restart = true;
while (restart) {
World world(10, 10);
God god;
world.addCharacter(Character("", 2, 2, "mineur", "travailleur", "homme"));
world.addCharacter(Character("", 3, 3, "mineur", "paresseux", "femme"));
world.addCharacter(Character("", 4, 4, "mineur", "courageux", "femme"));
world.addResource(Resource("bois", 5, 5, 50));
world.addResource(Resource("nourriture", 6, 6, 30));
world.addStockpile(Stockpile(7, 7));
string command;
for (int i = 0; i < 96; i++) {
world.display();
world.update();
cout << "Enter a command (e.g., 'control 0', 'release', 'role soldat', 'move 5 5') or 'n': ";
getline(cin, command);
if (command != "n") processCommand(god, world, command);
}
int choice;
cout << "\nSimulation ended. Choose an option:\n";
cout << "1. Exit\n";
cout << "2. Restart simulation\n";
cout << "3. Export logs to CSV\n";
cout << "Enter your choice (1-3): ";
cin >> choice;
cin.ignore();
switch (choice) {
case 1:
restart = false;
break;
case 2:
restart = true;
cout << "Restarting simulation...\n";
break;
case 3:
world.exportLogsToCSV();
cout << "Choose another option (1 to exit, 2 to restart): ";
cin >> choice;
cin.ignore();
if (choice == 1) restart = false;
else if (choice == 2) cout << "Restarting simulation...\n";
break;
default:
cout << "Invalid choice. Exiting...\n";
restart = false;
break;
}
}
return 0;
}
Version mise à jour 2.1.2 fonctionnelle (avant migration vers SFML)
simulation.cpp version 2.1.2
// Version 2.1.2 débuggée
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef _WIN32
#include // For detecting CMD and enabling ANSI support
#endif
using namespace std;
// ANSI color codes for highlighting
#define YELLOW_BG_BLACK_TEXT "\033[43;30m"
#define RESET_COLOR "\033[0m"
// Forward declarations to avoid order issues
class World;
class Character;
// Class Resource
class Resource {
public:
string type;
int x, y;
int quantity;
Resource(string t, int px, int py, int q) : type(t), x(px), y(py), quantity(q) {}
};
// Class Stockpile
class Stockpile {
public:
int x, y;
int wood;
Stockpile(int px, int py) : x(px), y(py), wood(0) {}
};
// Class Building
class Building {
public:
string type;
int x, y;
int occupancy; // Track how many Primak are using this building
Building(string t, int px, int py) : type(t), x(px), y(py), occupancy(0) {}
};
// Class to store logs for CSV export
class LogEntry {
public:
int day, hour;
string name, action;
int energy, hunger, wood, food, gestation, x, y;
LogEntry(int d, int h, string n, int e, int hu, int w, int f, int g, int px, int py, string a = "")
: day(d), hour(h), name(n), energy(e), hunger(hu), wood(w), food(f), gestation(g), x(px), y(py), action(a) {}
};
// Class World (déplacée avant Character pour que deposit puisse l'utiliser)
class World {
public:
vector characters;
vector resources;
vector stockpiles;
vector buildings;
vector logs;
int width, height;
int time;
int day;
string season;
int nextPrimakId;
bool useAnsiColors;
World(int w, int h) : width(w), height(h), time(0), day(1), season("printemps"), nextPrimakId(1) {
srand(static_cast(std::time(nullptr)));
#ifdef _WIN32
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD consoleMode;
useAnsiColors = GetConsoleMode(hConsole, &consoleMode);
if (useAnsiColors) {
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole, consoleMode);
}
#else
useAnsiColors = true;
#endif
}
void addCharacter(Character c);
void addResource(Resource r) { resources.push_back(r); }
void addStockpile(Stockpile s) { stockpiles.push_back(s); }
void addBuilding(Building b) { buildings.push_back(b); }
void display();
void update();
void exportLogsToCSV();
};
// Class Character (après World pour éviter les erreurs de déclaration)
class Character {
public:
string name;
int x, y;
string role;
int energy;
int hunger;
int wood;
int food;
string personality;
bool controlled;
bool alive;
string gender;
int gestation;
int procreationCooldown;
Character(string n, int px, int py, string r, string p, string g)
: name(n), x(px), y(py), role(r), energy(100), hunger(0), wood(0), food(0), personality(p), controlled(false), alive(true), gender(g), gestation(0), procreationCooldown(0) {}
void move(int newX, int newY) {
int energyCost = (gender == "femme") ? 12 : 8;
if (energy >= energyCost) {
x = newX;
y = newY;
energy -= energyCost;
hunger += (gender == "homme") ? 2 : 3;
}
}
void collect(Resource& res) {
int energyCost = (gender == "femme") ? 10 : 5;
if (energy >= energyCost && res.quantity > 0) {
res.quantity--;
energy -= energyCost;
hunger += (gender == "homme") ? 2 : 3;
if (res.type == "bois") wood++;
else if (res.type == "nourriture") food++;
}
}
void eat(Building* cantine = nullptr) {
if (cantine && cantine->type == "cantine" && x == cantine->x && y == cantine->y) {
hunger = max(0, hunger - 70);
cantine->occupancy++;
cout << name << " eats at the canteen and reduces hunger to " << hunger << endl;
} else if (food > 0) {
food--;
hunger = max(0, hunger - 30);
}
}
void deposit(Stockpile& stock, World& world) { // Corrigé avec World&
if (wood > 0 && x == stock.x && y == stock.y) {
stock.wood += wood;
cout << name << " deposits " << wood << " wood in the stockpile (total: " << stock.wood << ")" << endl;
wood = 0;
world.logs.push_back(LogEntry(world.day, world.time, "état du stockpile", 0, 0, 0, 0, 0, stock.x, stock.y, to_string(stock.wood)));
}
}
void sleep(Building* building = nullptr) {
if (building && building->type == "maison" && x == building->x && y == building->y) {
energy = min(100, energy + 30);
hunger = max(0, hunger - 50);
building->occupancy++;
cout << name << " sleeps in the house and recovers energy (" << energy << ") and hunger (" << hunger << ")" << endl;
} else if (building && building->type == "hotel" && x == building->x && y == building->y) {
energy = min(100, energy + 30);
building->occupancy++;
cout << name << " sleeps in the hotel and recovers energy (" << energy << ")" << endl;
} else {
energy = min(100, energy + 10);
}
hunger += (gender == "homme") ? 1 : 2;
}
void tryProcreate(vector& characters) {
if (gender == "femme" && gestation == 0 && procreationCooldown == 0 && energy >= 30 && hunger <= 70) {
for (auto& other : characters) {
if (&other != this && other.gender == "homme" && other.alive && !other.controlled && abs(x - other.x) <= 2 && abs(y - other.y) <= 2 && other.energy >= 30 && other.hunger <= 70) {
gestation = 24;
cout << name << " and " << other.name << " will have a child in 24h!" << endl;
break;
}
}
}
if (procreationCooldown > 0) procreationCooldown--;
}
};
// Class God
class God {
public:
Character* controlledCharacter = nullptr;
void takeControl(Character& c) {
if (!c.controlled && c.alive) {
controlledCharacter = &c;
c.controlled = true;
cout << "God takes control of " << c.name << endl;
}
}
void releaseControl() {
if (controlledCharacter) {
controlledCharacter->controlled = false;
cout << "God releases " << controlledCharacter->name << endl;
controlledCharacter = nullptr;
}
}
void changeRole(string newRole) {
if (controlledCharacter) {
controlledCharacter->role = newRole;
cout << controlledCharacter->name << " becomes " << newRole << endl;
}
}
};
// Définitions des méthodes de World
void World::addCharacter(Character c) {
c.name = "Primak" + to_string(nextPrimakId++);
characters.push_back(c);
}
void World::display() {
if (useAnsiColors) {
cout << YELLOW_BG_BLACK_TEXT << "Day " << day << " - Hour " << time << "h (" << season << ")" << RESET_COLOR << "\n";
} else {
cout << "Day " << day << " - Hour " << time << "h (" << season << ")\n";
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
bool printed = false;
for (auto& c : characters) {
if (c.x == x && c.y == y && c.alive) {
cout << (c.gender == "homme" ? "H" : "F");
printed = true;
break;
}
}
if (!printed) {
for (auto& b : buildings) {
if (b.x == x && b.y == y) {
if (b.type == "maison") cout << "M";
else if (b.type == "cantine") cout << "C";
else if (b.type == "hotel") cout << "O";
printed = true;
break;
}
}
}
if (!printed) {
for (auto& s : stockpiles) {
if (s.x == x && s.y == y) {
cout << "S";
printed = true;
break;
}
}
}
if (!printed) {
for (auto& r : resources) {
if (r.x == x && r.y == y && r.quantity > 0) {
cout << (r.type == "bois" ? "B" : "N");
printed = true;
break;
}
}
}
if (!printed) cout << ".";
}
cout << endl;
}
if (time % 6 == 0) {
cout << "Primak Stats:\n";
cout << left << setw(10) << "Name" << setw(10) << "Energy" << setw(10) << "Hunger" << setw(10) << "Wood" << setw(10) << "Food" << setw(15) << "Gestation" << "Position\n";
cout << string(65, '-') << endl;
for (const auto& c : characters) {
if (c.alive) {
cout << left << setw(10) << c.name << setw(10) << c.energy << setw(10) << c.hunger << setw(10) << c.wood << setw(10) << c.food << setw(15) << c.gestation << "(" << c.x << "," << c.y << ")\n";
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y));
}
}
cout << endl;
}
}
void World::update() {
vector newCharacters;
vector houseOccupancy(buildings.size(), 0);
vector hotelOccupancy(buildings.size(), 0);
vector canteenOccupancy(buildings.size(), 0);
for (auto& b : buildings) {
b.occupancy = 0;
}
for (auto& c : characters) {
if (c.alive && !c.controlled) {
if (time >= 20 || time < 8 || c.energy <= 20) {
Building* target = nullptr;
int targetDist = width + height;
int targetIndex = -1;
for (size_t i = 0; i < buildings.size(); ++i) {
auto& b = buildings[i];
int dist = abs(c.x - b.x) + abs(c.y - b.y);
if (b.type == "maison" && houseOccupancy[i] < 2) {
if (dist < targetDist) {
target = &b;
targetDist = dist;
targetIndex = i;
}
} else if (b.type == "hotel" && hotelOccupancy[i] < 10) {
if (dist < targetDist) {
target = &b;
targetDist = dist;
targetIndex = i;
}
}
}
if (target && targetDist > 0 && c.energy > 20) {
int newX = c.x + (c.x < target->x ? 1 : c.x > target->x ? -1 : 0);
int newY = c.y + (c.y < target->y ? 1 : c.y > target->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to (" + to_string(newX) + "," + to_string(newY) + ")"));
} else {
if (target && target->type == "maison" && targetIndex != -1) {
houseOccupancy[targetIndex]++;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Sleep in house"));
c.sleep(target);
} else if (target && target->type == "hotel" && targetIndex != -1) {
hotelOccupancy[targetIndex]++;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Sleep in hotel"));
c.sleep(target);
} else {
c.sleep();
}
}
} else if (time >= 8 && time < 20 && c.energy > 20) {
int closestDist = width + height;
Resource* closestRes = nullptr;
Stockpile* closestStock = nullptr;
Building* closestCantine = nullptr;
int canteenIndex = -1;
if (c.wood >= 2 || (c.wood > 0 && c.hunger >= 40)) {
for (auto& s : stockpiles) {
int dist = abs(c.x - s.x) + abs(c.y - s.y);
if (dist < closestDist) {
closestDist = dist;
closestStock = &s;
closestRes = nullptr;
closestCantine = nullptr;
}
}
} else {
for (auto& r : resources) {
if (r.quantity > 0) {
int dist = abs(c.x - r.x) + abs(c.y - r.y);
if (dist < closestDist && (r.type == "nourriture" || (r.type == "bois" && c.food > 0 && c.hunger < 40))) {
closestDist = dist;
closestRes = &r;
closestStock = nullptr;
closestCantine = nullptr;
}
}
}
for (auto& s : stockpiles) {
if (c.food > 0 && rand() % 10 < 8) {
int dist = abs(c.x - s.x) + abs(c.y - s.y);
if (dist < closestDist) {
closestDist = dist;
closestStock = &s;
closestRes = nullptr;
closestCantine = nullptr;
}
}
}
for (size_t i = 0; i < buildings.size(); ++i) {
auto& b = buildings[i];
if (b.type == "cantine" && c.hunger >= 40 && canteenOccupancy[i] < 10) {
int dist = abs(c.x - b.x) + abs(c.y - b.y);
if (dist < closestDist) {
closestDist = dist;
closestCantine = &b;
closestRes = nullptr;
closestStock = nullptr;
canteenIndex = i;
}
}
}
}
if (closestCantine && closestDist > 0) {
int newX = c.x + (c.x < closestCantine->x ? 1 : c.x > closestCantine->x ? -1 : 0);
int newY = c.y + (c.y < closestCantine->y ? 1 : c.y > closestCantine->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to canteen (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestCantine) {
canteenOccupancy[canteenIndex]++;
c.eat(closestCantine);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Eat at canteen"));
} else if (c.hunger >= 40 && c.food > 0) {
c.eat();
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Eat food"));
} else if (closestStock && closestDist > 0) {
int newX = c.x + (c.x < closestStock->x ? 1 : c.x > closestStock->x ? -1 : 0);
int newY = c.y + (c.y < closestStock->y ? 1 : c.y > closestStock->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to stockpile (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestStock) {
c.deposit(*closestStock, *this); // Appel corrigé avec World&
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Deposit wood"));
} else if (closestRes && closestDist > 0) {
int newX = c.x + (c.x < closestRes->x ? 1 : c.x > closestRes->x ? -1 : 0);
int newY = c.y + (c.y < closestRes->y ? 1 : c.y > closestRes->y ? -1 : 0);
c.move(newX, newY);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Move to resource (" + to_string(newX) + "," + to_string(newY) + ")"));
} else if (closestRes) {
c.collect(*closestRes);
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Collect resource"));
}
if (time >= 8 && time < 20) c.tryProcreate(characters);
}
c.hunger += (c.gender == "homme") ? 1 : 2;
if (c.hunger >= 100) {
c.energy -= 10;
if (c.energy <= 0) {
c.alive = false;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Died of hunger"));
}
}
if (c.gestation > 0) {
c.gestation--;
if (c.gestation == 0) {
string newName = "Primak" + to_string(nextPrimakId++);
characters.push_back(Character(newName, c.x, c.y, "mineur", "nouveau", (rand() % 2) ? "homme" : "femme"));
c.procreationCooldown = 24;
cout << c.name << " has given birth to a new Primak!" << endl;
logs.push_back(LogEntry(day, time, c.name, c.energy, c.hunger, c.wood, c.food, c.gestation, c.x, c.y, "Give birth"));
}
}
}
}
for (auto& newChar : newCharacters) {
characters.push_back(newChar);
}
bool needNewHouse = false, needNewCanteen = false, needNewHotel = false;
for (size_t i = 0; i < buildings.size(); ++i) {
if (buildings[i].type == "maison" && houseOccupancy[i] >= 2) needNewHouse = true;
if (buildings[i].type == "cantine" && canteenOccupancy[i] >= 10) needNewCanteen = true;
if (buildings[i].type == "hotel" && hotelOccupancy[i] >= 10) needNewHotel = true;
}
for (auto& s : stockpiles) {
if (s.wood >= 3) {
if (buildings.empty()) {
s.wood -= 3;
buildings.push_back(Building("maison", 7, 6));
cout << "A house has been built at (7,6) with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, 7, 6, "House"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
} else if (buildings.size() == 1 && s.wood >= 3) {
s.wood -= 3;
buildings.push_back(Building("cantine", 8, 7));
cout << "A canteen has been built at (8,7) with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, 8, 7, "Canteen"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
} else if (buildings.size() == 2 && s.wood >= 3) {
s.wood -= 3;
buildings.push_back(Building("hotel", 8, 8));
cout << "A hotel has been built at (8,8) with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, 8, 8, "Hotel"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
} else if (needNewHouse && s.wood >= 3) {
s.wood -= 3;
int newX = 7 + (buildings.size() % 3);
int newY = 6 + (buildings.size() % 3);
buildings.push_back(Building("maison", newX, newY));
cout << "A new house has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, newX, newY, "House"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
needNewHouse = false;
} else if (needNewCanteen && s.wood >= 3) {
s.wood -= 3;
int newX = 8 + (buildings.size() % 3);
int newY = 7 + (buildings.size() % 3);
buildings.push_back(Building("cantine", newX, newY));
cout << "A new canteen has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, newX, newY, "Canteen"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
needNewCanteen = false;
} else if (needNewHotel && s.wood >= 3) {
s.wood -= 3;
int newX = 8 + (buildings.size() % 3);
int newY = 8 + (buildings.size() % 3);
buildings.push_back(Building("hotel", newX, newY));
cout << "A new hotel has been built at (" << newX << "," << newY << ") with 3 wood from the stockpile!" << endl;
logs.push_back(LogEntry(day, time, "bâtiment construit", 0, 0, 0, 0, 0, newX, newY, "Hotel"));
logs.push_back(LogEntry(day, time, "état du stockpile", 0, 0, 0, 0, 0, s.x, s.y, to_string(s.wood)));
needNewHotel = false;
}
}
}
time++;
if (time >= 24) {
time = 0;
day++;
if (day % 91 == 0) {
if (season == "printemps") season = "ete";
else if (season == "ete") season = "automne";
else if (season == "automne") season = "hiver";
else if (season == "hiver") season = "printemps";
}
}
}
void World::exportLogsToCSV() {
ofstream file("simulation_logs.csv");
file << "Day,Hour,Name,Energy,Hunger,Wood,Food,Gestation,X,Y,Action\n";
for (const auto& log : logs) {
file << log.day << "," << log.hour << "," << log.name << "," << log.energy << "," << log.hunger << ","
<< log.wood << "," << log.food << "," << log.gestation << "," << log.x << "," << log.y << ","
<< "\"" << log.action << "\"" << "\n";
}
file.close();
cout << "Logs exported to simulation_logs.csv\n";
}
// Command interface
void processCommand(God& god, World& world, string command) {
stringstream ss(command);
string action;
ss >> action;
if (action == "control") {
int index;
ss >> index;
if (index >= 0 && index < world.characters.size()) {
god.takeControl(world.characters[index]);
}
} else if (action == "release") {
god.releaseControl();
} else if (action == "role") {
string newRole;
ss >> newRole;
god.changeRole(newRole);
} else if (action == "move") {
int x, y;
ss >> x >> y;
if (god.controlledCharacter) {
god.controlledCharacter->move(x, y);
}
}
}
int main() {
bool restart = true;
while (restart) {
World world(10, 10);
God god;
world.addCharacter(Character("", 2, 2, "mineur", "travailleur", "homme"));
world.addCharacter(Character("", 3, 3, "mineur", "paresseux", "femme"));
world.addCharacter(Character("", 4, 4, "mineur", "courageux", "femme"));
world.addResource(Resource("bois", 5, 5, 50));
world.addResource(Resource("nourriture", 6, 6, 30));
world.addStockpile(Stockpile(7, 7));
string command;
for (int i = 0; i < 96; i++) {
world.display();
world.update();
cout << "Enter a command (e.g., 'control 0', 'release', 'role soldat', 'move 5 5') or 'n': ";
getline(cin, command);
if (command != "n") processCommand(god, world, command);
}
int choice;
cout << "\nSimulation ended. Choose an option:\n";
cout << "1. Exit\n";
cout << "2. Restart simulation\n";
cout << "3. Export logs to CSV\n";
cout << "Enter your choice (1-3): ";
cin >> choice;
cin.ignore();
switch (choice) {
case 1:
restart = false;
break;
case 2:
restart = true;
cout << "Restarting simulation...\n";
break;
case 3:
world.exportLogsToCSV();
cout << "Choose another option (1 to exit, 2 to restart): ";
cin >> choice;
cin.ignore();
if (choice == 1) restart = false;
else if (choice == 2) cout << "Restarting simulation...\n";
break;
default:
cout << "Invalid choice. Exiting...\n";
restart = false;
break;
}
}
return 0;
}
Migration Visual Studio et SFML version 1
Configuration Initiale
- Configuration Initiale Migration vers Visual Studio
- SFML 3.0.0 GCC 14.2.0 MinGW (SEH) (UCRT)
- Chemin C:\SFML\bin
Dossier du projet
- PrimarkSimSFML
- .vscode
- c_cpp_properties.json
- launch.json
- setting.json
- tasks.json
- main.cpp
- sfml-graphics-3.dll
- sfml-system-3.dll
- sfml-window-3.dll
- World.cpp
- World.hpp
- .vscode
c_cpp_properties.json
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"C:/SFML/include"
],
"defines": [],
"compilerPath": "C:/msys64/ucrt64/bin/g++.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "C:\\msys64\\ucrt64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build active file"
}
]
}
settings.json
{
"C_Cpp.errorSquiggles": "disabled"
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "C:/msys64/ucrt64/bin/g++.exe", // Chemin complet pour éviter problèmes de PATH
"args": [
"-g",
"${file}",
"-I", "C:/SFML/include", // Chemin des headers
"-L", "C:/SFML/lib", // Chemin des bibliothèques
"-lsfml-graphics", // Lier SFML Graphics
"-lsfml-window", // Lier SFML Window
"-lsfml-system", // Lier SFML System
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
main.cpp
#include
#include
#include
#include
#include "World.hpp"
int main() {
sf::RenderWindow window(sf::VideoMode({500, 500}), "Primak Simulation");
World world(10, 10);
world.addCharacter(Character("", 2, 2, "mineur", "travailleur", "homme"));
world.addCharacter(Character("", 3, 3, "mineur", "paresseux", "femme"));
world.addResource(Resource("bois", 5, 5, 50));
world.addStockpile(Stockpile(7, 7));
while (window.isOpen()) {
std::optional event = window.pollEvent();
if (event && event->is()) {
window.close();
}
world.update();
world.display(window);
}
return 0;
}
World.cpp
#include "World.hpp"
#include
void World::display(sf::RenderWindow& window) {
window.clear(sf::Color::Black);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
sf::RectangleShape tile(sf::Vector2f(50.f, 50.f));
tile.setPosition(x * 50.f, y * 50.f);
tile.setFillColor(sf::Color(50, 50, 50));
bool drawn = false;
for (const auto& c : characters) {
if (c.x == x && c.y == y && c.alive) {
sf::CircleShape primak(20.f);
primak.setPosition(x * 50.f + 5.f, y * 50.f + 5.f);
primak.setFillColor(c.gender == "homme" ? sf::Color::Blue : sf::Color::Magenta);
window.draw(primak);
drawn = true;
break;
}
}
if (!drawn) {
for (const auto& b : buildings) {
if (b.x == x && b.y == y) {
tile.setFillColor(b.type == "maison" ? sf::Color::Red :
b.type == "cantine" ? sf::Color::Green :
sf::Color::Yellow);
window.draw(tile);
drawn = true;
break;
}
}
}
if (!drawn) {
for (const auto& s : stockpiles) {
if (s.x == x && s.y == y) {
tile.setFillColor(sf::Color::Cyan);
window.draw(tile);
drawn = true;
break;
}
}
}
if (!drawn) {
for (const auto& r : resources) {
if (r.x == x && r.y == y && r.quantity > 0) {
tile.setFillColor(r.type == "bois" ? sf::Color::Brown : sf::Color::White);
window.draw(tile);
drawn = true;
break;
}
}
}
if (!drawn) {
window.draw(tile);
}
}
}
window.display();
}
World.hpp
#ifndef WORLD_HPP
#define WORLD_HPP
#include
#include
#include // Ajout pour sf::RenderWindow
// Déclarations des classes (ajuste selon ton code réel)
class Character {
public:
std::string name;
int x, y;
std::string job, behavior, gender;
bool alive;
Character(std::string n, int px, int py, std::string j, std::string b, std::string g)
: name(n), x(px), y(py), job(j), behavior(b), gender(g), alive(true) {}
};
class Building {
public:
int x, y;
std::string type;
Building(int px, int py, std::string t) : x(px), y(py), type(t) {}
};
class Stockpile {
public:
int x, y;
Stockpile(int px, int py) : x(px), y(py) {}
};
class Resource {
public:
std::string type;
int x, y, quantity;
Resource(std::string t, int px, int py, int q) : type(t), x(px), y(py), quantity(q) {}
};
class World {
public:
int width, height;
std::vector characters;
std::vector buildings;
std::vector stockpiles;
std::vector resources;
World(int w, int h) : width(w), height(h) {}
void addCharacter(const Character& c) { characters.push_back(c); }
void addBuilding(const Building& b) { buildings.push_back(b); }
void addStockpile(const Stockpile& s) { stockpiles.push_back(s); }
void addResource(const Resource& r) { resources.push_back(r); }
void update(); // Déclaration
void display(sf::RenderWindow& window); // Déclaration avec SFML
};
#endif // WORLD_HPP
TITRE
SOUS TITRE
TEXTES