// cs_defense // // This program was written by Skye Tao (z5285195) // on 16/03/2023 // // TODO: Description of program #include #define MAP_ROWS 6 #define MAP_COLUMNS 12 //////////////////////////////////////////////////////////////////////////////// /////////////////////////// USER DEFINED TYPES //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// enum land_type { GRASS, WATER, PATH_START, PATH_END, PATH_UP, PATH_RIGHT, PATH_DOWN, PATH_LEFT, TELEPORTER }; enum entity { EMPTY, ENEMY, BASIC_TOWER, POWER_TOWER, FORTIFIED_TOWER, }; struct tile { enum land_type land; enum entity entity; int n_enemies; }; //////////////////////////////////////////////////////////////////////////////// //////////////////////// YOUR FUNCTION PROTOTYPE ///////////////////////////// //////////////////////////////////////////////////////////////////////////////// // TODO: Put your function prototypes here //////////////////////////////////////////////////////////////////////////////// ////////////////////// PROVIDED FUNCTION PROTOTYPE //////////////////////////// //////////////////////////////////////////////////////////////////////////////// void initialise_map(struct tile map[MAP_ROWS][MAP_COLUMNS]); void print_map(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money); void print_tile(struct tile tile, int entity_print); void valid_point(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money); void path_route(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col); int spawn_enemies(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col, int enemies); int basic_tower(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money); int moving_enemies(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col, int enemies); int tower_upgrade(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money); int main(void) { // This `map` variable is a 2D array of `struct tile`s. // It is `MAP_ROWS` x `MAP_COLUMNS` in size (which is 6x12 for this // assignment!) struct tile map[MAP_ROWS][MAP_COLUMNS]; // This will initialise all tiles in the map to have GRASS land and EMPTY // entity values. initialise_map(map); // TODO: Start writing code here! // TODO: Stage 1.1 - Scan in lives, money and start/ending points, then // print out the map! int lives; int money; int start_row; int start_col; int end_row; int end_col; int enemies; char check_character; printf("Starting Lives: "); scanf("%d", &lives); printf("Starting Money($): "); scanf("%d", &money); printf("Start Point: "); scanf("%d %d", &start_row, &start_col); map[start_row][start_col].land = PATH_START; //print_map(struct.land[start_row][start_col], lives, money); //struct.tile.land[start_row][start_col] = PATH_START; printf("End Point: "); scanf("%d %d", &end_row, &end_col); map[end_row][end_col].land = PATH_END; //print_map(struct.land[end_row][end_col], lives, money); //struct.tile.land[end_row][end_col] = PATH_END; print_map(map, lives, money); // TODO: Stage 1.2 - Scan in the initial enemies. Make sure you change the // `entity` at the starting position to be ENEMY, and that you update the // `n_enemies` value at that position to be this scanned value! printf("Initial Enemies: "); scanf("%d", &enemies); if (enemies > 0) { map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; print_map(map, lives, money); } else { print_map(map, lives, money); } printf("Enter Lake: "); valid_point(map, lives, money); printf("Enter Path: "); path_route(map, lives, money, start_row, start_col, end_row, end_col); printf("Enter Command: "); while(scanf(" %c", &check_character) == 1){ if (check_character == 'e') { enemies = spawn_enemies(map, lives, money, start_row, start_col, end_row, end_col, enemies); } else if (check_character == 't') { money = basic_tower(map, lives, money); } else if (check_character == 'm') { lives = moving_enemies(map, lives, money, start_row, start_col, end_row, end_col, enemies); } else if(check_character == 'u') { money = tower_upgrade(map, lives, money); } } printf("\nGame Over!\n"); } //////////////////////////////////////////////////////////////////////////////// ///////////////////////////// YOUR FUNCTIONS ////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // TODO: Put your functions here void valid_point(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money) { int row, column, height, width; scanf("%d %d %d %d", &row, &column, &height, &width); if (row + height > MAP_ROWS || column + width > MAP_COLUMNS) { printf("Error: Lake out of bounds, ignoring...\n"); print_map(map, lives, money); } else if (row < 0 || column < 0 || height < 0 || width < 0) { printf("Error: Lake out of bounds, ignoring...\n"); print_map(map, lives, money); } else { for (int i = row; i < row + height; i++) { for (int j = column; j < column + width; j++) { map[i][j].land = WATER; } } print_map(map, lives, money); } } void path_route(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col) { char input; while (start_row != end_row || start_col != end_col) { scanf(" %c", &input); if (input == 'l') { map[start_row][start_col].land = PATH_LEFT; start_col = start_col - 1; } else if (input == 'r') { map[start_row][start_col].land = PATH_RIGHT; start_col = start_col + 1; } else if (input == 'u') { map[start_row][start_col].land = PATH_UP; start_row = start_row - 1; } else if (input == 'd') { map[start_row][start_col].land = PATH_DOWN; start_row = start_row + 1; } } print_map(map, lives, money); } int spawn_enemies(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col, int enemies) { int new_enemies; scanf(" %d", &new_enemies); if (enemies >= 0) { enemies = enemies + new_enemies; map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; print_map(map, lives, money); } printf("Enter Command: "); return enemies; } int basic_tower(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money) { int tower_row; int tower_col; scanf(" %d %d", &tower_row, &tower_col); if ( money < 200 || tower_row < 0 || tower_row >= MAP_ROWS || tower_col < 0 || tower_col >= MAP_COLUMNS || map[tower_row][tower_col].land != GRASS || map[tower_row][tower_col].entity != EMPTY ) { printf("Error: Tower creation unsuccessful. Make sure you have at least $200 and that the tower is placed on a grass block with no entity.\n"); print_map(map, lives, money); } else { money = money - 200; printf("Tower successfully created!\n"); map[tower_row][tower_col].entity = BASIC_TOWER; print_map(map, lives, money); } printf("Enter Command: "); return money; } int moving_enemies(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money, int start_row, \ int start_col, int end_row, int end_col, int enemies) { int moving_steps; int i; int j; int times; scanf(" %d", &moving_steps); for (i = 0; i < MAP_ROWS; i++) { for (j = 0; j < MAP_COLUMNS; j++) { for (times = 0; times < moving_steps; times++) { if (map[i][j].land == PATH_LEFT) { map[i][j].entity = EMPTY; j = j - 1; } else if (map[i][j].land == PATH_RIGHT) { map[i][j].entity = EMPTY; j = j + 1; } else if (map[i][j].land == PATH_UP) { map[i][j].entity = EMPTY; i = i - 1; } else if (map[i][j].land == PATH_DOWN) { map[i][j].entity = EMPTY; i = i + 1; } } map[i][j].entity = ENEMY; map[i][j].n_enemies = enemies; } } if (map[i][j].entity == PATH_END) { printf("%d enemies reached the end!\n", enemies); lives = lives - enemies; print_map(map, lives, money); if (lives <= 0) { printf("Oh no, you ran out of lives!\n"); } } else if (map[i][j].entity != PATH_END) { printf("0 enemies reached the end!\n"); print_map(map, lives, money); } printf("Enter Command: "); return lives; } int tower_upgrade(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money) { int up_row; int up_col; scanf(" %d %d", &up_row, &up_col); if ( up_row < 0 || up_row >= MAP_ROWS || up_col < 0 || up_col >= MAP_COLUMNS ) { printf("Error: Upgrade target is out-of-bounds.\n"); print_map(map, lives, money); } else if ( map[up_row][up_col].entity != BASIC_TOWER && map[up_row][up_col].entity != POWER_TOWER && map[up_row][up_col].entity != FORTIFIED_TOWER ) { printf("Error: Upgrade target contains no tower entity.\n"); print_map(map, lives, money); } else if (map[up_row][up_col].entity == FORTIFIED_TOWER) { printf("Error: Tower cannot be upgraded further.\n"); print_map(map, lives, money); } else if (money < 300) { printf("Error: Insufficient Funds.\n"); print_map(map, lives, money); } else if (money > 300) { if (map[up_row][up_col].entity == BASIC_TOWER) { money = money - 300; map[up_row][up_col].entity = POWER_TOWER; printf("Upgrade Successful!\n"); print_map(map, lives, money); } else if (money < 500) { printf("Error: Insufficient Funds.\n"); print_map(map, lives, money); } else if (money >= 500) { if (map[up_row][up_col].entity == POWER_TOWER) { money = money - 500; map[up_row][up_col].entity = FORTIFIED_TOWER; printf("Upgrade Successful!\n"); print_map(map, lives, money); } } } printf("Enter Command: "); return money; } /* if (map[start_row][start_col].land == PATH_LEFT) { map[start_row][start_col].entity = EMPTY; map[start_row][start_col].n_enemies = 0; start_col = start_col - moving_steps; map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; } else if (map[start_row][start_col].land == PATH_RIGHT) { map[start_row][start_col].entity = EMPTY; map[start_row][start_col].n_enemies = 0; start_col = start_col + moving_steps; map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; } else if (map[start_row][start_col].land == PATH_UP) { map[start_row][start_col].entity = EMPTY; map[start_row][start_col].n_enemies = 0; start_row = start_row - moving_steps; map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; } else if (map[start_row][start_col].land == PATH_DOWN) { map[start_row][start_col].entity = EMPTY; map[start_row][start_col].n_enemies = 0; start_row = start_row + moving_steps; map[start_row][start_col].entity = ENEMY; map[start_row][start_col].n_enemies = enemies; } if (map[start_row][start_col].entity == PATH_END) { printf("%d enemies reached the end!\n", enemies); lives = lives - enemies; print_map(map, lives, money); if (lives <= 0) { printf("Oh no, you ran out of lives!\n"); } } else if (map[start_row][start_col].entity != PATH_END) { printf("0 enemies reached the end!\n"); print_map(map, lives, money); } return lives; */ //////////////////////////////////////////////////////////////////////////////// /////////////////////////// PROVIDED FUNCTIONS /////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /** * Initialises map tiles to contain GRASS land and EMPTY entity. * * Parameters: * map - The map to initialise. * Returns: * Nothing. */ void initialise_map(struct tile map[MAP_ROWS][MAP_COLUMNS]) { for (int row = 0; row < MAP_ROWS; ++row) { for (int col = 0; col < MAP_COLUMNS; ++col) { map[row][col].land = GRASS; map[row][col].entity = EMPTY; map[row][col].n_enemies = 0; } } } /** * Prints all map tiles based on their value, with a header displaying lives * and money. * * Parameters: * map - The map to print tiles from. * lives - The number of lives to print with the map. * money - The amount of money to print with the map. * Returns: * Nothing. */ void print_map(struct tile map[MAP_ROWS][MAP_COLUMNS], int lives, int money) { printf("\nLives: %d Money: $%d\n", lives, money); for (int row = 0; row < MAP_ROWS * 2; ++row) { for (int col = 0; col < MAP_COLUMNS; ++col) { print_tile(map[row / 2][col], row % 2); } printf("\n"); } } /** * Prints either the land or entity component of a single tile, based on * the `land_print` parameter; * * Parameters: * tile - The tile to print the land/entity from * land_print - Whether to print the land part of the tile or the entity * part of the tile. If this value is 0, it prints the land, otherwise * it prints the entity. * Returns: * Nothing. */ void print_tile(struct tile tile, int land_print) { if (land_print) { if (tile.land == GRASS) { printf(" . "); } else if (tile.land == WATER) { printf(" ~ "); } else if (tile.land == PATH_START) { printf(" S "); } else if (tile.land == PATH_END) { printf(" E "); } else if (tile.land == PATH_UP) { printf(" ^ "); } else if (tile.land == PATH_RIGHT) { printf(" > "); } else if (tile.land == PATH_DOWN) { printf(" v "); } else if (tile.land == PATH_LEFT) { printf(" < "); } else if (tile.land == TELEPORTER) { printf("( )"); } else { printf(" ? "); } } else { if (tile.entity == EMPTY) { printf(" "); } else if (tile.entity == ENEMY) { printf("%03d", tile.n_enemies); } else if (tile.entity == BASIC_TOWER) { printf("[B]"); } else if (tile.entity == POWER_TOWER) { printf("[P]"); } else if (tile.entity == FORTIFIED_TOWER) { printf("[F]"); } else { printf(" ? "); } } }