Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I have this monopoly clone that I need to add the ability to save and load from a save but I have no idea where to even begin so any help is appreciated!

GitHub - Mitul-Joby/Monopoly: An implementation of the board game monopoly in C, in your terminal.[^]

What I have tried:

Logging every dice roll but the player names get corrupted
Posted
Updated 15-Feb-24 1:44am

It very much depends on what the existing code does. In general terms you would just write data to a file to save, and read from the file to reload. But the exact implementation will very much depend on the structure of the existing code.

See Stream I/O | Microsoft Learn[^].
 
Share this answer
 
We can't give you a specific answer to this: we have no idea what you tried, or any familiarity with the software - and I for one am not going to wade through the whole of a github project to work out how it works before trying to add features.

If you want to add features to an existing project, you need to understand pretty much the whole project first: just "logging dice rolls" isn't going to help because that isn't even close the all the info you need to restore the game so far: it's not compulsory to buy a property you land on, the Chance and Community Chest cards are in random order, and so forth.

So go to the github project and examine it carefully: when you know how it works, you can start thinking about mods but not before!
 
Share this answer
 
You are lucky, the existing code already loads the 'locations' from a file ('locations.csv' in the 'data' folder). Have a look at the ReadLocations funciton and use it as reference for implementing your (say) ReadPlayers one.
Then, with the acquired experience, you could easily write the complementary WritePlayers code as well.
 
Share this answer
 
Quote:
Logging every dice roll but the player names get corrupted

After first analyzing the game, it does not seem to make sense to log individual dice rolls if the goal is to load or save the current game state. The log would perhaps make sense if you wanted to track every single move.

The fact that the player name and other variables are overwritten is due to the fact that several parts of the source code have already been implemented incorrectly.

Example:
In the mainGame() function, things go massively wrong right at the start:
C
while (GamemodeChoice == NETWORTH) {
    char inp[1];        // <-- here!!!
    printf("\n\n\tEnter maximum net worth after which game is to end: ");
    scanf("%s",&inp);   // <-- here!!!
    if (atoi(inp) >= 1400){
        maxNetworth=atoi(inp);
        break;
    }
    printf("\n\n\tInvalid Input (Enter a number from greater than 1400) \n\tEntered: %s\n",inp);
}

The field for a string containing at least one character must be at least 2 bytes in size. If, as in the previous case, a multi-digit decimal number is to be entered, the buffer must be correspondingly larger. Buffer overflows could be avoided even with minimal changes.
C
while (GamemodeChoice == NETWORTH) {
    char inp[6];
    printf("\n\n\tEnter maximum net worth after which game is to end (min. 1400): ");
    scanf("%5s",&inp);
    if (atoi(inp) >= 1400){
        maxNetworth=atoi(inp);
        break;
    }
    printf("\n\n\tInvalid Input (Enter a number from greater than 1400) \n\tEntered: %s\n",inp);
}

Since other data or return addresses on the stack are obviously overwritten when user input is read in, a good compiler should notice this. I have also integrated the minimum expected value into the prompt, as otherwise you would have to guess first.

I assume that save and load means that the last game state should be saved or restored. It is necessary to save the player data and the state of the properties. Logging past or future actions seems unnecessary.

The first step would be to analyze what exactly should be saved.

Most of the structures to be saved are in the definitions.h file. The properties are stored in the struct location.
Initially, the key figures and names are loaded from the locations.csv file and would not necessarily have to be be saved and loaded twice if the locations.csv file is read in beforehand anyway.
C
struct location {       
    unsigned int ID :6;
    unsigned int type:3;    
    // ...
} location[40];

In order to save the score, the number of players and their possessions should be saved, preferably in one file.
C
struct player {
    unsigned int ID:4;
    char name[30];  
    // ...
}

The game generates event cards at random, so nothing can be saved here in this version. In addition, further status-dependent details might have to be saved.

I suggest writing a function save_game_score() and a function load_game_score() and adding the item "Load last game" to the menu. In order to save the score at any point, a key, possibly a function key, would have to be documented and implemented.

When testing the program under Windows, it is particularly annoying that the program is terminated if the command window is not the right size. This should be changed so that the program is easier to debug from the development environment.
Here is the improved version for Windows, which adjusts the window to the size instead of closing the program.
C
#ifdef _WIN32
#include <windows.h>

void checkWindowSize(int screenWidth, int screenHeight)
{
     CONSOLE_SCREEN_BUFFER_INFO csbi;
     HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
     if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) {
         printf("Error: GetConsoleScreenBufferInfo (%d)\n", GetLastError());
         exit(1);
     }

     SMALL_RECT srctWindow = csbi.srWindow;
     int width = srctWindow.Right - srctWindow.Left + 1;
     int height = srctWindow.Bottom - srctWindow.Top + 1;

     if (width < screenWidth || height < screenHeight) {
        if(width < screenWidth) 
             srctWindow.Right = screenWidth;
        if(height < screenHeight)
             srctWindow.Bottom = screenHeight;

        COORD wbuff = { screenWidth +1, screenHeight +1 };

        SetConsoleScreenBufferSize(hStdout, wbuff);
        SetConsoleWindowInfo( hStdout, TRUE, &srctWindow);

        // printf("\nTerminal size is too small. Please resize terminal.");
        // printf("\nSuggested size: %d X %d", screenWidth, screenHeight);
        // printf("\nCurrent size  : %d X %d", width, height);
        // printf("\n\n");
        // exit(1);
}

As already said, the code has many weaknesses, ranging from uninitialized variables to stack problems. In the ReadPlayers() function, for example, a stack overflow occurs which the debugger reports.
Here, scanf and %s are used to read a string into an array with one byte, which looks unhealthy.
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900