Projet Primark

Structure Initiale en C++ avec programiz.pro

				
					#include <iostream>
#include <vector>
#include <string>
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<Character> characters;
    vector<Resource> 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
Version fonctionnelle 2.1.1
				
					{
    "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"
        }
    ]
}
				
			
				
					{
    "files.associations": {
        "iostream": "cpp"
    }
}
				
			
				
					{
    "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
            }
        }
    ]
}
				
			
				
					// Version 2.1.1
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <fstream>
#ifdef _WIN32
#include <windows.h> // 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<Character>& 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<Character> characters;
    vector<Resource> resources;
    vector<Stockpile> stockpiles;
    vector<Building> buildings;
    vector<LogEntry> 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<unsigned>(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<Character> newCharacters;
        vector<int> houseOccupancy(buildings.size(), 0);
        vector<int> hotelOccupancy(buildings.size(), 0);
        vector<int> 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 <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <fstream>
#ifdef _WIN32
#include <windows.h> // 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<Character> characters;
    vector<Resource> resources;
    vector<Stockpile> stockpiles;
    vector<Building> buildings;
    vector<LogEntry> 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<unsigned>(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<Character>& 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<Character> newCharacters;
    vector<int> houseOccupancy(buildings.size(), 0);
    vector<int> hotelOccupancy(buildings.size(), 0);
    vector<int> 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
				
					{
    "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
}
				
			
				
					{
    "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"
        }
    ]
}
				
			
				
					{
    "C_Cpp.errorSquiggles": "disabled"
}
				
			
				
					{
    "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
            }
        }
    ]
}
				
			
				
					#include <SFML/Graphics.hpp>
#include <SFML/Window/Event.hpp>
#include <iostream>
#include <optional>
#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<sf::Event> event = window.pollEvent();
        if (event && event->is<sf::Event::Closed>()) {
            window.close();
        }

        world.update();
        world.display(window);
    }

    return 0;
}
				
			
				
					#include "World.hpp"
#include <SFML/Graphics.hpp>

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();
}
				
			
				
					#ifndef WORLD_HPP
#define WORLD_HPP

#include <vector>
#include <string>
#include <SFML/Graphics.hpp> // 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<Character> characters;
    std::vector<Building> buildings;
    std::vector<Stockpile> stockpiles;
    std::vector<Resource> 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