int damage_calculation(int enemy_move, int command1, int *atk, int *hp, int *spd, int *def, int
*opp_atk, int *opp_spd, int *opp_hp, int *opp_def, int *charge_turn, int *opp_charge, int
*block, int *opp_block)
{
int damage = *atk - *opp_def;
int opp_damage = *opp_atk - *def;
// Decreases charge of player for next turn
if (*charge_turn > 0) {
*charge_turn -= 1;
*atk /= 2;
*spd /= 2;
}
// Decreases charge of opponent for next turn
if (*opp_charge > 0) {
*opp_charge -= 1;
*opp_atk /= 2;
*opp_spd /= 2;
}
// Decreases block of the player for next turn
if (*block > 0) {
*block -= 1;
*def /= 2;
}
// Decreases block for next turn for the opponent
if (*opp_block > 0) {
*opp_block -= 1;
*opp_def /= 2;
}
// Checks if the user will have the first move or attack at the same time
if (*spd >= *opp_spd) {
if (*atk < *opp_def) {
damage = 0;
} else if (enemy_move == 2) {
*def *= 2;
*opp_block += 1;
} else if (command1 == 2) {
*def *= 2;
*block += 1;
} else if (command1 == 3 && *charge_turn == 0) {
*charge_turn = 1;
*atk *= 2;
*spd *= 2;
damage = 0;
} else if (command1 == 1) {
*opp_hp -= damage;
}
// Your opponent's turn when you move first
if (*opp_atk < *def) {
opp_damage = 0;
} else if (enemy_move == 3 && *opp_charge == 0) {
*opp_charge += 1;
*opp_atk *= 2;
*opp_spd *= 2;
opp_damage = 0;
} else if (enemy_move == 1) {
*hp -= opp_damage;
}
}
// Checks if the opponent has the first move
if (*opp_spd > *spd) {
if (*opp_atk < *def) {
opp_damage = 0;
} else if (enemy_move == 2) {
*def *= 2;
*opp_block += 1;
} else if (command1 == 2) {
*def *= 2;
*block += 1;
} else if (enemy_move == 3) {
*opp_charge += 1;
*opp_atk *= 2;
*opp_spd *= 2;
opp_damage = 0;
} else if (enemy_move == 1) {
*hp -= opp_damage;
}
// Your turn when the opponent moves first
if (*atk < *opp_def) {
damage = 0;
} else if (command1 == 3) {
*opp_charge += 1;
*atk *= 2;
*spd *= 2;
damage = 0;
} else if (command1 == 1) {
*opp_hp -= damage;
}
}
// Displays what the enemy decided to do
if (enemy_move == 1) {
printf("Your opponent's move is Attack!\n");
} else if (enemy_move == 2) {
printf("Your opponent's move is Block!\n");
} else if (enemy_move == 3) {
printf("Your opponent's move is Charge!\n");
}
// Will display current stats and show who is the winner and the loser
if (*hp <= 0 || *hp < 0) {
printf("Your HP is 0!\n");
printf("You lose!\n");
} else if (*opp_hp <= 0 || *opp_hp < 0) {
printf("Your opponent's HP is 0!\n");
printf("You win!\n");
} else if (*hp > 0 && *opp_hp > 0) {
printf("Your updated stats:\n");
printf("HP = %d\n", *hp);
printf("ATK = %d\n", *atk);
printf("DEF = %d\n", *def);
printf("SPD = %d\n\n", *spd);
printf("Your opponent's updated stats:\n");
printf("HP = %d\n", *opp_hp);
printf("ATK = %d\n", *opp_atk);
printf("DEF = %d\n", *opp_def);
printf("SPD = %d\n\n\n", *opp_spd);
}
return enemy_move, command1, *atk, *hp, *spd, *def, *opp_atk, *opp_spd, *opp_hp, *opp_def,
*charge_turn, *opp_charge, *block, *opp_block;
}
I am currently a beginner in c and I am trying to create a turn based game. I want to be able to do 3 moves which are attack, block, and charge. My problem with the function that I created which is named int damage_calculation()
. I created is that whenever I decide to input 2 or 3 which represents block or charge. They won’t update properly. The rules for block is that the move block will always go first and that the opponent or the user’s defense will only double in that turn but will go back to normal the next turn. I also have the same problem going on with my charge. I want it to be able to make sure that the user or the opponent will take damage depending on what the move of their opponent does and I want to be able to update my attack and speed values by multiplying them both by 2. In the end of the next turn I want them to be able to go back to their normal values. For some reason the defense of the user won’t decrease when I divide it by 2 in the next turn and the defense of the opponent keeps decreasing every turn. My charges are also more or less doing the same thing.
I am doing this for a project which have rules such as only being able to use the current topics we have learned which are functions (excluding recursions), pointers, loops, if else statements. We aren’t allowed to do anything else other than those mentioned. command1 represents the input of the user between the 3 moves and enemy_moves represents the randomly generated move done by the opponent which is the pc. I tried creating integer variables called block, opp_block, charge_turn, and opp_charge which i initialized them all to 0 in my main function. I tried updating their values inside the damage calculation function but for some reason I am not getting the results I want.
Reviewing what you are attempting to do in building this game, I was not so much trying to figure out any specific coding techniques that were “wrong” or “right”, but rather try to expand upon one of the good comments about possibly utilizing the entity known as a “structure” for bundling information when calling a function that is supposed to analyze what is happening in a game. Objects such as players in a game that have certain attributes are good candidates for structures.
With that, following is some sample code with the “battle” function redefined and simplified. FYI, even though simplified, the code will be a bit verbose.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Player
{
char name[40];
int move;
int damage;
int charge;
int block;
int atk;
int hp;
int def;
int spd;
};
void damage_calculation(struct Player *player1, struct Player *player2)
{
// Displays what player #1 decided to do
if (player1->move == 1)
{
printf("%s's move is Attack!\n", player1->name);
}
else if (player1->move == 2)
{
printf("%s's move is Block!\n", player1->name);
}
else if (player1->move == 3)
{
printf("%s's move is Charge!\n", player1->name);
}
player1->damage = player1->atk - player2->def;
// Decreases charge of player for next turn
if (player1->charge > 0)
{
player1->charge -= 1;
player1->atk /= 2;
player1->spd /= 2;
}
// Decreases block of the player for next turn
if (player1->block > 0)
{
player1->block -= 1;
player1->def /= 2;
}
// Checks if the user will have the first move or attack at the same time
if (player1->spd >= player2->spd)
{
if (player1->atk < player2->def)
{
player1->damage = 0;
}
else if (player2->move == 2)
{
player1->def *= 2;
player2->block += 1;
}
else if (player1->move == 2)
{
player1->def *= 2;
player1->block += 1;
}
else if (player1->move == 3 && player1->charge == 0)
{
player1->charge = 1;
player1->atk *= 2;
player1->spd *= 2;
player1->damage = 0;
}
else if (player1->move == 1)
{
player2->hp -= player2->damage;
}
}
// Displays what player #2 decided to do
if (player2->move == 1)
{
printf("%s's move is Attack!\n", player2->name);
}
else if (player2->move == 2)
{
printf("%s's move is Block!\n", player2->name);
}
else if (player2->move == 3)
{
printf("%s's move is Charge!\n", player2->name);
}
// Will display current stats and show who is the winner and the loser
if (player1->hp <= 0)
{
printf("%s HP is 0!\n", player1->name);
printf("%s loses and %s wins!\n", player1->name, player2->name);
}
else if (player2->hp <= 0)
{
printf("%s HP is 0!\n", player2->name);
printf("%s loses and %s wins!\n", player2->name, player1->name);
}
else if (player1->hp > 0 && player2->hp > 0)
{
printf("%s updated stats:\n", player1->name);
printf("HP = %d\n", player1->hp);
printf("ATK = %d\n", player1->atk);
printf("DEF = %d\n", player1->def);
printf("SPD = %d\n\n", player1->spd);
printf("%s updated stats:\n", player2->name);
printf("HP = %d\n", player2->hp);
printf("ATK = %d\n", player2->atk);
printf("DEF = %d\n", player2->def);
printf("SPD = %d\n\n", player2->spd);
}
return;
}
int main()
{
struct Player player1, player2;
strcpy(player1.name, "The Good Guy"); /* Give each player a name */
strcpy(player2.name, "The Bad Guy");
player1.hp = 10; /* Initialize each player with some values */
player1.atk = 4;
player1.def = 6;
player1.spd = 22;
player2.hp = 14;
player2.atk = 2;
player2.def = 8;
player2.spd = 12;
player1.move = 1; /* Set up the initial battle */
player2.move = 2;
damage_calculation(&player1, &player2);
player2.move = 1; /* Repeat - this time for player #2 */
player1.move = 2;
damage_calculation(&player2, &player1);
return 0;
}
Some key points to consider:
-
Since multiple but consistent data will be processed in the battle, this data can be bundled within a “Player” structure which then can be passed and used in the program logic.
-
Instead of defining a function that requires a large number of input parameters and attempts to output multiple return values, the function is simplified to pass along references to the two players via the player structure.
-
Passing information to a function via pointer reference allows for the swapping of the players which allows for some simplification within the programming of the function.
Testing this out with some simplified function calls in a program prototype yielded the following terminal output illustrating how the players can “take turns”.
craig@Vera:~/C_Programs/Console/EnemyMoves/bin/Release$ ./EnemyMoves
The Good Guy's move is Attack!
The Bad Guy's move is Block!
The Good Guy updated stats:
HP = 10
ATK = 4
DEF = 6
SPD = 22
The Bad Guy updated stats:
HP = 14
ATK = 2
DEF = 8
SPD = 12
The Bad Guy's move is Attack!
The Good Guy's move is Block!
The Bad Guy updated stats:
HP = 14
ATK = 2
DEF = 8
SPD = 12
The Good Guy updated stats:
HP = 10
ATK = 4
DEF = 6
SPD = 22
This prototype code is not so much to convince you that structures should be used, but rather to provide a coding path that may not have been thought about. And it might provide impetus to seek out tutorials and information on “C” programming with structures.
The function should be rewritten anew with much less parameters. Use structures to combine properties. Otherwise your function is awful.
And try to simplify the logic. Make separate functions for each move, instead of checking the move all over the place in
if
statements.Functions should, ideally, have a singular responsibility. This function does way too much, and should be broken down into smaller, more easily tested functions.
This
return enemy_move, command1, *atk, *hp, *spd, *def, *opp_atk, ..., *opp_block;
does not do what I believe you expect it to do.Do you want speed and defense to always be the default value at the start of each turn, or do you want, e.g., multiple blocks on successive turns to accumulate defense?
Show 3 more comments