Untitled

mail@pastecode.io avatar
unknown
plain_text
7 months ago
10 kB
0
Indexable
Never
#include <iostream>

#include <fstream>

#include <string>

#include "logic.h"




using std::cout, std::endl, std::ifstream, std::string;




/**

 * TODO: Student implement this function

 * Load representation of the dungeon level from file into the 2D map.

 * Calls createMap to allocate the 2D array.

 * @param   fileName    File name of dungeon level.

 * @param   maxRow      Number of rows in the dungeon table (aka height).

 * @param   maxCol      Number of columns in the dungeon table (aka width).

 * @param   player      Player object by reference to set starting position.

 * @return  pointer to 2D dynamic array representation of dungeon map with player's location., or nullptr if loading fails for any reason

 * @updates  maxRow, maxCol, player

 */

char** loadLevel(const string& fileName, int& maxRow, int& maxCol, Player& player) {

    std::ifstream file(fileName);

    if (!file) {

        std::cerr << "Error loading level: " << fileName << std::endl;

        return nullptr;

    }




    // Read the dimensions of the level from the file

    file >> maxRow >> maxCol;




    // Allocate memory for the map

    char** map = createMap(maxRow, maxCol);




    // Read the map from the file

    for (int i = 0; i < maxRow; ++i) {

        for (int j = 0; j < maxCol; ++j) {

            file >> map[i][j];

            if (map[i][j] == TILE_PLAYER) {

                player.row = i;

                player.col = j;

            }

        }

    }




    // Update the player's initial position to 'o'

    map[player.row][player.col] = TILE_PLAYER;




    return map;

}




/**

 * TODO: Student implement this function

 * Translate the character direction input by the user into row or column change.

 * That is, updates the nextRow or nextCol according to the player's movement direction.

 * @param   input       Character input by the user which translates to a direction.

 * @param   nextRow     Player's next row on the dungeon map (up/down).

 * @param   nextCol     Player's next column on dungeon map (left/right).

 * @updates  nextRow, nextCol

 */

void getDirection(char input, int& nextRow, int& nextCol) {

    switch (input) {

        case MOVE_UP:

            nextRow = -1;

            nextCol = 0;

            break;

        case MOVE_DOWN:

            nextRow = 1;

            nextCol = 0;

            break;

        case MOVE_LEFT:

            nextRow = 0;

            nextCol = -1;

            break;

        case MOVE_RIGHT:

            nextRow = 0;

            nextCol = 1;

            break;

        default:

            break;

    }

}




/**

 * TODO: [suggested] Student implement this function

 * Allocate the 2D map array.

 * Initialize each cell to TILE_OPEN.

 * @param   maxRow      Number of rows in the dungeon table (aka height).

 * @param   maxCol      Number of columns in the dungeon table (aka width).

 * @return  2D map array for the dungeon level, holds char type.

 */

char** createMap(int maxRow, int maxCol) {

    char** map = new char*[maxRow];

    for(int i = 0; i < maxRow; ++i)

        map[i] = new char[maxCol];




    for(int i = 0; i < maxRow; ++i)

        for(int j = 0; j < maxCol; ++j)

            map[i][j] = TILE_OPEN;




    return map;

}




/**

 * TODO: Student implement this function

 * Deallocates the 2D map array.

 * @param   map         Dungeon map.

 * @param   maxRow      Number of rows in the dungeon table (aka height).

 * @return None

 * @update map, maxRow

 */

void deleteMap(char**& map, int& maxRow) {

    for (int i = 0; i < maxRow; ++i) {

        delete[] map[i];

    }

    delete[] map;

}




/**

 * TODO: Student implement this function

 * Resize the 2D map by doubling both dimensions.

 * Copy the current map contents to the right, diagonal down, and below.

 * Do not duplicate the player, and remember to avoid memory leaks!

 * You can use the STATUS constants defined in logic.h to help!

 * @param   map         Dungeon map.

 * @param   maxRow      Number of rows in the dungeon table (aka height), to be doubled.

 * @param   maxCol      Number of columns in the dungeon table (aka width), to be doubled.

 * @return  pointer to a dynamically-allocated 2D array (map) that has twice as many columns and rows in size.

 * @update maxRow, maxCol

 */

char** resizeMap(char** map, int& maxRow, int& maxCol) {

    int newMaxRow = maxRow * 2;

    int newMaxCol = maxCol * 2;




    char** newMap = new char*[newMaxRow];

    for (int i = 0; i < newMaxRow; ++i) {

        newMap[i] = new char[newMaxCol];

    }




    // Initialize new map with empty spaces

    for (int i = 0; i < newMaxRow; ++i) {

        for (int j = 0; j < newMaxCol; ++j) {

            newMap[i][j] = TILE_OPEN;

        }

    }




    // Copy old map into new map

    for (int i = 0; i < maxRow; ++i) {

        for (int j = 0; j < maxCol; ++j) {

            newMap[i * 2][j * 2] = map[i][j];

        }

    }




    // Delete old map

    for (int i = 0; i < maxRow; ++i) {

        delete[] map[i];

    }

    delete[] map;




    maxRow = newMaxRow;

    maxCol = newMaxCol;




    return newMap;

}




/**

 * TODO: Student implement this function

 * Checks if the player can move in the specified direction and performs the move if so.

 * Cannot move out of bounds or onto TILE_PILLAR or TILE_MONSTER.

 * Cannot move onto TILE_EXIT without at least one treasure.

 * If TILE_TREASURE, increment treasure by 1.

 * Remember to update the map tile that the player moves onto and return the appropriate status.

 * You can use the STATUS constants defined in logic.h to help!

 * @param   map         Dungeon map.

 * @param   maxRow      Number of rows in the dungeon table (aka height).

 * @param   maxCol      Number of columns in the dungeon table (aka width).

 * @param   player      Player object to by reference to see current location.

 * @param   nextRow     Player's next row on the dungeon map (up/down).

 * @param   nextCol     Player's next column on dungeon map (left/right).

 * @return  Player's movement status after updating player's position.

 * @update map contents, player

 */

int doPlayerMove(char** map, int maxRow, int maxCol, Player& player, int nextRow, int nextCol) {

    char nextPosition = map[nextRow][nextCol];




    // Check if the next position is an empty space, a door, or a treasure

    if (nextPosition == TILE_OPEN || nextPosition == TILE_DOOR || nextPosition == TILE_TREASURE) {

        // Update the player's position

        map[player.row][player.col] = TILE_OPEN;

        player.row = nextRow;

        player.col = nextCol;

        map[player.row][player.col] = TILE_PLAYER;




        // Check if the next position is a treasure

        if (nextPosition == TILE_TREASURE) {

            player.treasure++;

            return STATUS_TREASURE;

        }




        // Check if the next position is a door

        if (nextPosition == TILE_DOOR) {

            // Check if the player has at least one treasure to exit

            if (player.treasure > 0) {

                return STATUS_LEAVE;

            } else {

                // Player cannot exit without treasures

                return STATUS_STAY;

            }

        }




        // Player moved to an empty space

        return STATUS_MOVE;

    }




    // Invalid move: player hit a wall or encountered a monster

    return STATUS_STAY;

}




/**

 * TODO: Student implement this function

 * Update monster locations:

 * We check up, down, left, right from the current player position.

 * If we see an obstacle, there is no line of sight in that direction, and the monster does not move.

 * If we see a monster before an obstacle, the monster moves one tile toward the player.

 * We should update the map as the monster moves.

 * At the end, we check if a monster has moved onto the player's tile.

 * @param   map         Dungeon map.

 * @param   maxRow      Number of rows in the dungeon table (aka height).

 * @param   maxCol      Number of columns in the dungeon table (aka width).

 * @param   player      Player object by reference for current location.

 * @return  Boolean value indicating player status: true if monster reaches the player, false if not.

 * @update map contents

 */

bool doMonsterAttack(char** map, int maxRow, int maxCol, const Player& player) {

    char** tempMap = createMap(maxRow, maxCol);

    for (int i = 0; i < maxRow; ++i) {

        for (int j = 0; j < maxCol; ++j) {

            tempMap[i][j] = map[i][j];

        }

    }




    // Update monster locations

    for (int i = 0; i < maxRow; ++i) {

        for (int j = 0; j < maxCol; ++j) {

            if (tempMap[i][j] == TILE_MONSTER) {

                // Move monsters one tile toward the player

                int rowDiff = player.row - i;

                int colDiff = player.col - j;




                if (abs(rowDiff) >= abs(colDiff)) {

                    // Move vertically

                    tempMap[i][j] = TILE_OPEN;

                    i += (rowDiff > 0) ? 1 : -1;

                    tempMap[i][j] = TILE_MONSTER;

                } else {

                    // Move horizontally

                    tempMap[i][j] = TILE_OPEN;

                    j += (colDiff > 0) ? 1 : -1;

                    tempMap[i][j] = TILE_MONSTER;

                }




                // Check if monster has reached the player's tile

                if (i == player.row && j == player.col) {

                    deleteMap(tempMap, maxRow);

                    return true; // Player is caught by a monster

                }

            }

        }

    }




    // Update the original map with the new monster positions

    for (int i = 0; i < maxRow; ++i) {

        for (int j = 0; j < maxCol; ++j) {

            map[i][j] = tempMap[i][j];

        }

    }




    // Clean up the temporary map

    deleteMap(tempMap, maxRow);




    return false; // Player is not caught by a monster

}