COMP 2012H Honors Object-Oriented Programming and Data Structures

Assignment 3 SimpleCity

Announcements

  • Updated October 28: Deadline was postponed to November 8.

Honor Code

We value academic integrity very highly. Please read the Honor Code section on our course webpage to make sure you understand what is considered as plagiarism and what the penalties are. The following are some of the highlights:

  • Do NOT try your "luck" - we use sophisticated plagiarism detection software to find cheaters. We also review codes for potential cases manually.
  • The penalty (for BOTH the copier and the copiee) is not just getting a zero in your assignment. Please read the Honor Code thoroughly.
  • Serious offenders will fail the course immediately, and there will be additional disciplinary actions from the department and university, upto and including expulsion.

Objectives & Intended Learning Outcomes

The objective of this assignment is to provide you with practice on the OOP concepts of Inheritance and Polymorphism, as well as writing code with less reliance on a provided skeleton code. Upon completion of this assignment, you should be able to:

  1. Write appropriate header files on your own, without being provided them as part of the skeleton code.
  2. Manage dynamic memory effectively with the use of class constructors and destructors.
  3. Use inheritance to allow for significant code reuse between base classes and derived classes.
  4. Use function overriding in derived classes to provide different function implementations for the same member function prototype.
  5. Understand how base class pointers/references can point/refer to derived class objects, yet polymorphically call derived class functions that are declared virtual.
  6. Code a program following the OOP paradigm.
Git illustration

Introduction

In this and the coming assignment, you are going to implement a simple city simulation game, which we call it SimpleCity. In this assignment, you first implement the game logic that can be presented in a command-line program. In the next assignment, you are going to implement the graphical user interface (GUI) for the game.

The game consists of a city. A city consists of a square grid where buildings can be constructed on each grid cell. Also, a city has a budget for building constructions. A building can be built only if the cost to construct the building does not exceed the budget. At most one building can be constructed in each grid cell.

There are three categories of buildings:

  • Residential buildings: These buildings house population for the city.
  • Revenue buildings: These buildings provide revenue which increases the budget of the city. The amount of revenue depends on the population of the city.
  • Health buildings: These buildings provide growth of population.

Therefore, it requires all three categories of buildings for a city to grow in both population and budget.

There are six types of buildings, each type of building belongs to one category:

  • Residential buildings: House, Apartment
  • Revenue buildings: Silver Mine, Gold Mine
  • Health buildings: Clinic, Hospital

Buildings of the same category share some common attributes. The building hierarchy is visualized in the following diagram:

Game Mechanics

  • At start, the Player is prompted to take one of two actions:
    1. Starting a new game. The Player is prompted to enter the size of the square grid, which is an even number between 10 and 20 inclusive. Then, a new city is created. The initial budget is $150.
    2. Loading an existing game from file. The Player is prompted to enter the filename of the save. Then, the city is loaded from the save.
  • City simulation takes turn. During a turn, the Player can perform the following three actions for arbitrary number of times:
    1. Constructing a building at a grid cell. The Player is prompted to select the type of the building and enter the coordinates of the grid cell to build. The building can be constructed only if the cost does not exceed the budget and the grid cell has no buildings. If the building is constructed, the budget is reduced by the cost of the building. Here are the cost of each type of buildings:
      • House: $50
      • Apartment: $300
      • Silver Mine: $50
      • Gold Mine: $400
      • Clinic: $50
      • Hospital: $500
    2. Demolishing a building at a grid cell. The Player is prompted to enter the coordinates of the grid cell to demolish. The building at the grid cell is removed. This action does not reduce budget.
    3. Saving the city to a file to be loaded later.
  • When the Player decides to make a turn, the following steps are performed:
    1. The turn number of the city is increased by one.
    2. The budget of the city is increased by the sum of revenue generated by all Revenue buildings.
      • For Silver Mines, the revenue is city's population + population in neighboring buildings.
      • For Gold Mines, the revenue is 2 * (city's population + population in neighboring buildings).
      • The city's population is the sum of population of all Residential buildings.
    3. The population is increased by the following steps.
      1. The population growth rate of the city is calculated, as the sum of population growth rate contribution of each building:
        • For Residential buildings, it is -population of the building.
        • For Clinics, it is 60 / (1 + number of neighboring Health buildings).
        • For Hospitals, it is 360 / (1 + number of neighboring Health buildings).
        • For other buildings, it is 0.
      2. For each Residential building, the maximum population is calculated:
        • For Houses, it is 50 * (1 + neighboring Residential building)
        • For Apartments, it is 250 * (1 + neighboring Residential building)
      3. For each Residential building, the population growth (can be negative) is calculated, as the minimum of two terms:
        1. population growth rate of the city * (number of neighboring Health buildings - number of neighboring Gold Mines) / 10
        2. The remaining population: maximum population - population
      4. For each Residential building, the population is increased (or decreased) by its population growth.
        • If the new population exceeds the max population, set it to the max population.
        • If the new population is smaller than 0, set it to 0.
        • The new population does not affect population population of other buildings. You need to save the population growth of each Residential building and apply them in a batch.
  • This figure illustrates a city grid with size 12.
    The yellow grid cells are the neighbors of the red grid cells.

Save File Format

The save file is a plaintext file that stores each value on a new line.
  • The first three values are the grid size, budget and turns of the city.
  • Then followed by each cell in the grid, in the order of
    grid[0][0], grid[0][1], ... ,grid[1][0], grid[1][1], ..., grid[grid_size - 1][0], ...
    • If the grid cell has no building, save 0
    • If the grid cell has a building, save the value in the Building::Type enum (See Building.h in Code Structure). For example, 1 denotes a Clinic.
    • For Residential building, also store the population after a space. For example, 5 10 denotes a House with 10 population.
The following example is the save of a city with 2x2 grid, $100 budget at turn 5. Two buildings were constructed: A Clinic at grid[0][0], a House with 10 population at grid[1][1]:

                2
                100
                5
                1
                0
                0
                5 10

              
It is optional to have an empty line at the end.

Code Structure


                pa3
                ├── City.cpp
                ├── City.h
                ├── GameEngine.cpp
                ├── GameEngine.h
                ├── Makefile
                ├── buildings/
                │   ├── Apartment.cpp
                │   ├── Apartment.h
                │   ├── Building.cpp
                │   ├── Building.h
                │   ├── BuildingInformationFormatString.h
                │   ├── Clinic.cpp
                │   ├── Clinic.h
                │   ├── GoldMine.cpp
                │   ├── GoldMine.h
                │   ├── Health.cpp
                │   ├── Health.h
                │   ├── Hospital.cpp
                │   ├── Hospital.h
                │   ├── House.cpp
                │   ├── House.h
                │   ├── Residential.cpp
                │   ├── Residential.h
                │   ├── Revenue.cpp
                │   ├── Revenue.h
                │   ├── SilverMine.cpp
                │   └── SilverMine.h
                ├── main_cli.cpp
                ├── test-city.txt
                ├── test-info.txt
                └── test-load.txt
              
  • Makefile: Makefile to build SimpleCity and create ZINC submission zip file. See Submission & Grading
  • GameEngine.h, GameEngine.cpp: Code for the implemented command-line game engine. No need to modify.
  • main_cli.cpp: The main() function. No need to modify.
  • City.h, City.cpp: Implementation of the City class. Implement the methods in City.cpp. Do not modify City.h
  • buildings/Building.h, buildings/Building.cpp: Implementation of the Building abstract base class. Implement the methods in Building.cpp. Do not modify Building.h
  • buildings/BuildingInformationFormatString.h: Contains useful strings to display building information.
  • Other files in buildings/: Implementations of classes derived from Building. Complete the class declarations in corresponding .h files. Implement the methods in corresponding .cpp file.
  • test-city.txt, test-info.txt and test-load.txt: Three save files for testing.
  • 
                      class City {
                      public:
                          struct Coordinates {
                              int x;
                              int y;
    
                              ...
                          };
    
                          ...
    
                      private:
                          Building ***grid;
                          int grid_size;
                          int budget;
                          int turn;
                      };
                    

    The City class is defined in City.h. It has four private members. grid is a 2D dynamic array of building pointers. The 2D array is always a square. The size of it is specified in grid_size. budget denotes the budget of the city. turn is the turn of the city.

    The Coordinates struct is used to specify the coordinates of a particular grid cell in some methods of the City class. For (x,y) coordinates, it refers to the grid cell grid[x][y].

    When Building objects are added to the city, the city takes ownership of the Building objects.

  • 
                      class Building {
                      public:
                          enum class Type {
                              CLINIC = 1,
                              HOSPITAL = 2,
                              SILVER_MINE = 3,
                              GOLD_MINE = 4,
                              HOUSE = 5,
                              APARTMENT = 6
                          };
    
                          enum class Category {
                              HEALTH,
                              REVENUE,
                              RESIDENTIAL
                          };
    
                          ...
    
                      protected:
                          explicit Building(City &city);
    
                          City &city;
    
                      private:
                          Building *neighboring_buildings[4]{};
                      };
                    

    The Building class is defined in Building.h. It holds a reference to the city where the building was constructed. This city reference. The constructor is marked as protected, meaning that it is not possible to create a Building instance. The constructor and the city reference can only be accessed from derived classes. neighboring_buildings is an array of 4 pointers to buildings, all initialized to nullptr. This is used to access the neighboring buildings when computing some attributes of the building.

    Two enum classes for the building type and building category are also defined. Integer values for the building type are also defined. You may want to use static_cast to convert between building type and the corresponding integer value when processing save files.

Part 1: City

Implement the following functions of the City class.

  • 
                      City(int size);
                    
    Creates a new City. Allocate the 2D array of grid cells with dimensions size by size. Set all grid cells to nullptr. Set grid size accordingly. Set turn to 1. Initially, the budget is $150. size is always greater than or equal to 1.
  • 
                      City(const std::string &filename);
                    
    Loads a city from the file filename. See Save File Format for the format of the save file. You can assume the file always exists and the format is correct. You can make use of the >> operator. Don't forget to set neighbors when adding buildings to the city.
  • 
                      ~City();
                    
    Deallocates all dynamically allocated memory, including the memory of Building objects added to the city.
  • 
                      save(const std::string& filename) const;
                    
    Saves the city to a file such that it can be loaded later. If the file already exists, overwrite existing content. You can make use of the << operator.
  • 
                      int get_turn() const;
                      int get_budget() const;
                      int get_grid_size() const;
                    
    Returns the turn, budget and grid size of the city, respectively.
  • 
                      int get_revenue() const;
                      int get_population() const;
                      int get_max_population() const;
                      int get_population_growth() const;
                      int get_population_growth_rate() const;
                    
    Returns the corresponding attribute of the city.
    • The revenue of the city is the sum of revenue of all buildings in the city.
    • The population of the city is the sum of population of all buildings in the city.
    • The max population of the city is the sum of max population of all buildings in the city.
    • The population growth of the city is the sum of population growth of all buildings in the city.
    • The population growth rate of the city is the sum of population growth rate contribution of all buildings in the city.
  • 
                      Building *get_at(const Coordinates &coordinates) const;
                    
    Returns a pointer to the building at the grid cell specified by the coordinates. Return nullptr if the cell has no buildings or the coordinates are out-of-bound.
  • 
                      bool is_empty_at(const Coordinates &coordinates) const;
                    
    Returns whether the grid cell specified by the coordinates is empty (has no buildings). Return false if the coordinates are out-of-bound.
  • 
                      bool can_construct(Building::Type type) const;
                      bool can_construct(Building::Type type, const Coordinates &coordinates) const;
                    
    Returns whether the city has enough budget to construct the given type of building. If coordinates are provided, also check whether the building can be constructed at the grid cell specified by the coordinates. Return false if the coordinates are out-of-bound.
  • 
                      bool construct_at(Building::Type type, const Coordinates &coordinates);
                    
    Constructs a building with the specified type at the grid cell specified by the coordinates. If the building cannot be constructed (with reasons mentioned above), then return false. Otherwise, construct the building by setting the grid pointer accordingly, decrease budget and register neighboring buildings. For residential buildings, set the population to 0. Return true.
  • 
                      bool demolish_at(const Coordinates &coordinates);
                    
    Demolishes the building at the grid cell specified by the coordinates. If the coordinates are out-of-bound or the grid cell is empty, return false. Otherwise, demolish the building by setting the grid pointer accordingly and deregister neighboring buildings. Return true.
  • 
                      void move_to_next_turn();
                    
    Proceeds to next turn by following the steps in Game Mechanics.

Part 2: Buildings

Implement the following functions of the Building class and its derived classes.

  • 
                      Building(City &city);
    
                      Health(City &city);
                      Clinic(City &city);
                      Hospital(City &city);
    
                      Revenue(City &city);
                      SilverMine(City &city);
                      GoldMine(City &city);
    
                      Residential(City &city, int population);
                      House(City &city, int population);
                      Apartment(City &city, int population);
                    
    A reference of the city where the building is constructed is passed to the constructor. The population of residential buildings is also passed to the constructor. You may need to store the population of residential buildings in a private data member.
  • 
                      virtual ~Building() = default;
                    
    The default destructor is used, so no need to implement destructors.
  • 
                      virtual Building::Type get_type() const = 0;
                      virtual Building::Category get_category() const = 0;
                      virtual int get_cost() const = 0;
                    
    Returns the building type, category and cost, respectively. For example, an apartment has the type Building::Type::APARTMENT, category Building::Category::RESIDENTIAL and cost 300.
    
                      static const int cost{0};
                    
    It is helpful to store the cost in a static data member. In this way, the cost is associated with the class itself. We can obtain the cost from the class before making an instance.
  • 
                      virtual std::string get_long_information() const = 0;
                      virtual std::string get_short_information() const = 0;
                    
    Returns the long and short information string of the building, respectively. For short information string, output the building type, followed by attribute specific to that type of the building. For long information string, also output the formula of each attribute. Refer to BuildingInformationFormatString.h for the information strings.
    • Clinic:
      
                            Clinic
                            Contribution to Population Growth Rate: [value]
                          
      
                            Clinic
                            Contribution to Population Growth Rate: [value]
                            60 / (1 + Neighboring Health Buildings)
                          
    • Hospital:
      
                            Hospital
                            Contribution to Population Growth Rate: [value]
                          
      
                            Hospital
                            Contribution to Population Growth Rate: [value]
                            360 / (1 + Neighboring Health Buildings)
                          
    • Silver Mine:
      
                            Silver Mine
                            Revenue: [value]
                          
      
                            Silver Mine
                            Revenue: [value]
                            1 * (Total Population + Neighboring Population)
                          
    • Gold Mine:
      
                            Gold Mine
                            Revenue: [value]
                          
      
                            Gold Mine
                            Revenue: [value]
                            2 * (Total Population + Neighboring Population)
                          
    • House. The quota is max population - population:
      
                            House
                            Population: [value]
                            Max Population: [value]
                            Contribution to Population Growth Rate: [value]
                            Population Growth: [value]
                          
      
                            House
                            Population: [value]
                            Max Population: [value]
                            50 * (1 + Neighboring Residential Buildings)
                            Contribution to Population Growth Rate: [value]
                            -population
                            Population Growth: [value] (Limited by Quota: [value])
                            (Population Growth Rate of the City * (Neighboring Health Buildings - Neighboring Gold Mines)) / 10
                          
    • Apartment. The quota is max population - population:
      
                            Apartment
                            Population: [value]
                            Max Population: [value]
                            Contribution to Population Growth Rate: [value]
                            Population Growth: [value]
                          
      
                            Apartment
                            Population: [value]
                            Max Population: [value]
                            250 * (1 + Neighboring Residential Buildings)
                            Contribution to Population Growth Rate: [value]
                            -population
                            Population Growth: [value] (Limited by Quota: [value])
                            (Population Growth Rate of the City * (Neighboring Health Buildings - Neighboring Gold Mines)) / 10
                          
  • 
                      virtual int get_revenue() const;
                    
    Returns the revenue of the building. Default to 0 except for Revenue buildings.
    • For Silver Mines, it is city's population + population in neighboring buildings.
    • For Gold Mines, it is 2 * (city's population + population in neighboring buildings).
  • 
                      virtual int get_population() const;
                    
    Returns the population of the building. Default to 0 except for Residential buildings.
  • 
                      virtual int get_max_population() const;
                    
    Returns the max population of the building. Default to 0 except for Residential buildings.
    • For Houses, it is 50 * (1 + neighboring Residential building).
    • For Apartments, it is 250 * (1 + neighboring Residential building).
  • 
                      virtual int get_population_growth() const;
                    
    Returns the population growth of the building. Default to 0 except for Residential buildings. For residential buildings, it is the minimum of two terms. Use integer division:
    1. population growth rate of the city * (number of neighboring Health buildings - number of neighboring Gold Mines) / 10.
    2. The remaining population: maximum population - population.
  • 
                      virtual int get_population_growth_rate_contribution() const;
                    
    Returns the contribution of population growth rate of the building to the city. Default to 0 except for Health buildings and Residential buildings. Use integer division.
    • For Residential buildings, it is -population of the building.
    • For Clinics, it is 60 / (1 + number of neighboring Health buildings).
    • For Hospitals, it is 360 / (1 + number of neighboring Health buildings).
  • 
                      virtual void increase_population(int population);
                    
    Increases the population of the building. Default to no action except for Residential buildings.
    • If the new population exceeds the max population, set it to the max population.
    • If the new population is smaller than 0, set it to 0.
  • 
                      bool register_neighboring_building(Building *building);
                      bool deregister_neighboring_building(Building *building);
                    
    Common functions for all types of building. [Registers/Deregisters] the building referred by the pointer (never a nullptr) to the neighboring_buildings array. If the building is already [registered/already unregistered, or not registered], return false. Otherwise, return true. The order of buildings in the array does not matter.
  • 
                      int number_neighboring_residential_buildings() const;
                      int number_neighboring_health_buildings() const;
                      int number_neighboring_gold_mines() const;
                      int number_neighboring_population() const;
                    
    Common functions for all types of building.
    • Returns the number of neighboring buildings that are Residential buildings.
    • Returns the number of neighboring buildings that are Health buildings.
    • Returns the number of neighboring buildings that are Gold Mines.
    • Returns the sum of population in neighboring buildings.

Example

In the skeleton files, you can find the save file test-city.txt. Here are the city status and city map.


                Turn: 8
                Budget: $3
                Revenue: 99
                Max Population: 200
                Population: 35
                Population Change: 25
                Population Growth Rate: 85
              
   0123456789
  +----------+
 0|          |
 1|          |
 2|          |
 3|    S     |
 4|    EEC   |
 5|    CCS   |
 6|          |
 7|          |
 8|          |
 9|          |
  +----------+
  • For the Clinics at (4,5) and (5,5), the number of neighboring Health buildings are 1. Therefore, their contribution to population growth rate is 60 / 2 = 30.
    
                      Clinic
                      Contribution to Population Growth Rate: 30
                      60 / (1 + Neighboring Health Buildings)
                    
  • For the Clinic at (6,4), the number of neighboring Health buildings are 0. Therefore, its contribution to population growth rate is 60 / 1 = 60.
    
                      Clinic
                      Contribution to Population Growth Rate: 60
                      60 / (1 + Neighboring Health Buildings)
                    
  • For the Silver Mine at (6,5), the total population is 35, and the number of neighboring population is 0. Therefore, its revenue is 35 + 0 = 35.
    
                      Silver Mine
                      Revenue: 35
                      1 * (Total Population + Neighboring Population)
                    
  • For the Silver Mine at (4,3), the total population is 35, and the number of neighboring population is 29 (the population of the House at (4,3) is 29). Therefore, its revenue is 35 + 29 = 64.
    
                      Silver Mine
                      Revenue: 64
                      1 * (Total Population + Neighboring Population)
                    
  • For the House at (4,4), the population is 29. For the House at (5,4), the population is 6. Therefore, the contribution to population growth rate of the two houses are -29 and -6. As a result, the population growth rate of the city is -29 - 6 + 30 + 30 + 60 = 85 (including Health buildings).

    For the House at (4,4), the neighboring Residential buildings is 1, the neighboring Health buildings is 1, and the neighboring Gold Mines is 0. Therefore, the population growth is 85 * (1 - 0) / 10 = 8, and the max population is 50 * (1 + 1) = 100.

    
                      House
                      Population: 29
                      Max Population: 100
                      50 * (1 + Neighboring Residential Buildings)
                      Contribution to Population Growth Rate: -29
                      -population
                      Population Growth: 8 (Limited by Quota: 71)
                      (Population Growth Rate of the City * (Neighboring Health Buildings - Neighboring Gold Mines)) / 10
                    

    For the House at (5,4), the neighboring Residential buildings is 1, the neighboring Health buildings is 2, and the neighboring Gold Mines is 0. Therefore, the population growth is 85 * (2 - 0) / 10 = 17, and the max population is 50 * (1 + 1) = 100.

    
                      House
                      Population: 6
                      Max Population: 100
                      50 * (1 + Neighboring Residential Buildings)
                      Contribution to Population Growth Rate: -6
                      -population
                      Population Growth: 17 (Limited by Quota: 94)
                      (Population Growth Rate of the City * (Neighboring Health Buildings - Neighboring Gold Mines)) / 10
                    
  • At the next turn, the budget is increased to 3 + (35 + 64) = $102. Population of the House at (4,4) is increased to 29 + 8 = 37. Population of the House at (5,4) is increased to 6 + 17 = 23. The total population is 37 + 23 = 60.
    
                      Turn: 9
                      Budget: $102
                      Revenue: 157
                      Max Population: 200
                      Population: 60
                      Population Change: 18
                      Population Growth Rate: 60
                    

Compilation

Use the Makefile provided in the skeleton file for compilation. Simply run make in the directory that contains main_cli.cpp and Makefile. After successful compilation, an executable, simplecity (or simplecity.exe) will be produced.

Note: If you are a Windows user and you wish to run simplecity.exe outside VSCode, change line 6 of Makefile from:


                LDFLAGS :=
              
to:

                LDFLAGS := -static
              

Resources

Submission & Grading

Deadline: 8 November 2021 Monday HKT 23:59.
You may earn 8% course grade for each PA via Automated Grading on the ZINC Online Submission System. Please check here for a usage overview of ZINC.

Files to Submit

There are a number of files you need to submit to ZINC. A Makefile target is provided to automate the creation of the zip file. Run the following command in the directory that contains Makefile:


                make pa3.zip
              

Then, pa3.zip is produced. Submit pa3.zip to ZINC. It contains the following files:

  • City.cpp
  • buildings/Building.cpp
  • buildings/Health.h
  • buildings/Health.cpp
  • buildings/Revenue.h
  • buildings/Revenue.cpp
  • buildings/Residential.h
  • buildings/Residential.cpp
  • buildings/Clinic.h
  • buildings/Clinic.cpp
  • buildings/Hospital.h
  • buildings/Hospital.cpp
  • buildings/SilverMine.h
  • buildings/SilverMine.cpp
  • buildings/GoldMine.h
  • buildings/GoldMine.cpp
  • buildings/House.h
  • buildings/House.cpp
  • buildings/Apartment.h
  • buildings/Apartment.cpp

Late Submission Policy

There will be a penalty of -1 point (out of a maximum 100 points) for every minute you are late. For instance, since the deadline is 23:59:00 on 8 November 2021, if you submit your solution at 1:00:00 on 9 November 2021, there will be a penalty of -61 points for your assignment. However, the lowest grade you may get from an assignment is zero: any negative score after the deduction due to late penalty (and any other penalties) will be reset to zero.

Test Cases

Here are the revealed test cases on ZINC and the input.

  • Test #1
    Start a new city, print status and map, then quit.
    
                  
  • Test #2
    Start a new city, attempt to construct some buildings, then quit.
    
                  
  • Test #3
    Start a new city, construct a building, attempt to demolish some buildings, then quit.
    
                  
  • Test #4
    Load a city from test-load.txt, print status and map, then quit.
    
                  
  • Test #5
    Load a city from test-info.txt, print the short and long information string for each type of building, then quit.
    
                  
  • Test #6
    Load a city from test-city.txt, move to next turn, check status, move to a few turns later, check status, then quit.
    
                  

Memory Leak

Before the program terminates, you need to ensure you have deallocated all dynamic memory you have allocated in the entire execution of the program.

Memory leak is checked by using the sanitizer, invoked by the -fsanitize=address,leak,undefined option (See related documentation here). Some revealed test cases on ZINC also check for memory leak (See Test Cases).

Checking Memory Leak Yourself

Although some test cases on ZINC already check for memory leak, you may still want to check for memory leak yourself. However, the above option does not work in Windows minGW g++. Instead, you can do so by remote connecting using SSH to the machines in the Linux Lab (Lab 2). The following shows you how to do so by using the Virtual Barn. You may want to adjust the steps accordingly if you are familiar with using SSH on your own computer.

  1. Remote control a Windows machine in HKUST virtual barn. After following the installation guide and user guide there to install the remote control client and connect to the HKUST network, choose the Programming Software server when you are offered a selection of different servers.
  2. Copy your files to Virtual Barn. If you have no idea, you can email yourself the files and then download them there.
  3. Open PuTTY. There is a shortcut on your Desktop. Enter a lab 2 machine (csl2wkXX.cse.ust.hk, where XX=[01 ... 53], for example csl2wk13.cse.ust.hk) as the Host Name. Note: If that server doesn't work, you may try other servers by changing XX.
  4. Click Open. If a warning about the security key shows up, click Yes to dismiss it.
  5. Enter your CSD login and password. (Register one if you haven't done so in lab 1 by following the lab 1 instructions.) It may not show what you type when you are typing in the password. Don't worry, just type your password and hit the Enter key. You should login to your home directory. Enter the command pwd (Print Working Directory) to verify this. It should show /homes/your_login
  6. Open FileZilla from Start Menu. Click "File" -> "Site Manager" -> "New Site". Choose SFTP for protocol according to the screenshot below. Enter csl2wk13.cse.ust.hk (or the server you used in the previous step) as Host. Choose "Ask for password" for the Logon Type.
  7. Click Connect and then enter your CSD login and password.
  8. If the connection succeeds, the right side should show your home directory at Linux Lab. Copy all PA2 files including cpp files, header files, the include directory, by dragging them to the right side. Do NOT drag a folder containing all those files, instead, you should drag the files themselves only. That would upload the individual files (without any folder) to /homes/your_login. Also, you need to use this Makefile in the machines in Linux Lab. This Makefile includes the sanitizer option on compilation. You can close FileZilla after doing so.
  9. Go back to PuTTY, and compile your program using the make command:
    
                        make
                      
  10. If no compilation errors occurred, you should be able to run your program by:
    
                        ./simplecity
                      
  11. Note: Memory leak check is enabled along with other runtime errors check for your program. If there are any errors, some error messages (just like what you would see in the Error tab on Zinc) will appear in the terminal as you run your program.

Acknowledgments

This assignment was originally proposed and designed by Yu Hei CHAU.