[Programming - C] character generator for a game

Click For Summary
SUMMARY

The forum discussion centers on a C programming implementation for a character generator in a game. The provided code includes structures for character attributes, functions for rolling stats and calculating bonuses, and user prompts for input. Key issues identified include the improper use of the MAX_STAT constant, which is defined but not utilized, and the suggestion to bundle stats with their bonuses into a single structure for improved maintainability. Additionally, the hitpoint calculation method was scrutinized for correctness.

PREREQUISITES
  • Understanding of C programming language syntax and structures
  • Familiarity with random number generation in C using srand and rand
  • Knowledge of basic game mechanics related to character attributes and hitpoints
  • Experience with debugging and optimizing C code for maintainability
NEXT STEPS
  • Implement the suggested StatWithBonus structure to combine stats and bonuses
  • Refactor the code to utilize MAX_STAT for loop boundaries instead of magic numbers
  • Review and validate the hitpoint calculation logic for accuracy
  • Explore advanced C programming techniques for structuring game data more efficiently
USEFUL FOR

Game developers, C programmers, and anyone interested in creating character generation systems for role-playing games will benefit from this discussion.

iroattoyou
Messages
1
Reaction score
0
Context:
3b5e9878a6fd235e45eb2e3e6d56ebf4.png

2b439244c28e64d4320c273fb3617579.png

FguROec.png

JWpphi7.png


Question:
5a854aa3d6f797ce242b4374db03e85e.png

75ddda9e22ba67c54b8963faf5170a4e.png


Code I have thusfar:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define MAX_STAT


enum {
    STR, DEX, INT, CON, WIS, CHA, LEVEL, MAX_STAT
};
struct Character {
    int level;
    int class;
    int HP;
    int bonus[8];
    int stats[MAX_STAT];
};
struct Character myCharacter;
void roll_stat(int *stat_to_be_rolled);
void get_bonus(int *bonus_to_be_calculated, int base_stat);
int roll_hp(int char_level);
int main(void)
{
    /* Declare stat variables */
    char stats_label[7][6];
    /* = "Level", "Str", "Dex", "Con", "Int", "Wis", "Cha"; */
    /* Declare control variables */
    int stat_loop, accept = 0;
    /* Seed the random number generator */
    srand((unsigned) time(NULL));
    /* Store labels in a string. This helps us later on to easily print them */
    strcpy(stats_label[0], "Level");
    strcpy(stats_label[1], "Str");
    strcpy(stats_label[2], "Dex");
    strcpy(stats_label[3], "Con");
    strcpy(stats_label[4], "Int");
    strcpy(stats_label[5], "Wis");
    strcpy(stats_label[6], "Cha");
    while (!accept) {
	/* prompt and read in level */
	printf("Please enter Level: ");
	scanf("%d", &myCharacter.stats[0]);
	/* roll stats */
	for (stat_loop = 1; stat_loop < 7; stat_loop++)
	    roll_stat(&myCharacter.stats[stat_loop]);
	/* calculate bonuses */
	myCharacter.bonus[0] = roll_hp(myCharacter.stats[0]);
	for (stat_loop = 1; stat_loop < 7; stat_loop++)
	    get_bonus(&myCharacter.bonus[stat_loop],
		      myCharacter.stats[stat_loop]);
	/* print the stats out for acceptance */
	printf("%s: %d ", stats_label[0], myCharacter.stats[0]);
	for (stat_loop = 1; stat_loop < 7; stat_loop++)
	    printf("%s: %d %d ", stats_label[stat_loop],
		   myCharacter.stats[stat_loop],
		   myCharacter.bonus[stat_loop]);
	printf("Hitpoints: %d\n", myCharacter.bonus[0]);
	/* check for loop exit condition */
	printf
	    ("Do you want to accept these? (enter 1 to accept, 0 to reroll): ");
	scanf("%d", &accept);
    }
    /* print stats in required formatted block */
    printf("[%s] [%d]\n", stats_label[0], myCharacter.stats[0]);
    for (stat_loop = 1; stat_loop < 7; stat_loop++)
	printf("[%s]: [%d] [%d] \n", stats_label[stat_loop],
	       myCharacter.stats[stat_loop], myCharacter.bonus[stat_loop]);
    printf("[Hitpoints]: [%d]\n", myCharacter.bonus[0]);
    return (0);
}

/* Roll 4d6 and drop lowest */
void roll_stat(int *stat_to_be_rolled)
{
    int dice1, dice2, dice3, dice4, total;
    /* Roll 4d6 */
    dice1 = (rand() % 6 + 1);
    dice2 = (rand() % 6 + 1);
    dice3 = (rand() % 6 + 1);
    dice4 = (rand() % 6 + 1);
    /* Find lowest dice and add result of the other 3 */
    if ((dice1 < dice2) && (dice1 < dice3) && (dice1 < dice4))
	total = dice2 + dice3 + dice4;
    else if ((dice2 < dice1) && (dice2 < dice3) && (dice2 < dice4))
	total = dice1 + dice3 + dice4;
    else if ((dice3 < dice1) && (dice3 < dice2) && (dice3 < dice4))
	total = dice1 + dice2 + dice4;
    else
	total = dice1 + dice2 + dice3;
    /* assign total value to the memory location we were given */
    *stat_to_be_rolled = total;
}

/* This was extracted as a function to make the bonus loop more compact */
void get_bonus(int *bonus_to_be_calculated, int base_stat)
{
    if (base_stat > 9)
	*bonus_to_be_calculated = (base_stat - 10) / 2;
    else
	*bonus_to_be_calculated = (base_stat - 11) / 2;
}

/* This was extracted as a function to make the HP loop more compact */
int roll_hp(int char_level)
{
    int hploop = 0, hp = 0;
    /* printf("Leve1: %d", char_level); For testing */
    for (hploop = 0; hploop < char_level; hploop++)
	hp += (rand() % 6 + 1);
    return (hp);
}

http://pastebin.com/Gs8rfGs2

d y : a dice of Y sides (ie d6)

x d y: X number of Y sided dice (ie: 3d6 = 3 x 6 sided dice)

Hitdice: The type of dice rolled for hit-points or a Class/Profession. (ie: d4, d6, d8)

Skill Structure: struct Skill { char name[20], char optional[20], char short_desc[250], int stat_affinity, int ranks, struct Skill *next_Skill;};

Class Structure: struct Class { char name[20]; int Hitdice, Str_Dice, Dex_Dice, Con_Dice, Int_Dice, Wis_Dice, Cha_Dice, Skill_Points; double BAB_Type; struct Class *next_Class;)};

Is my hitpoint formula correct? Does my code seem to satisfy the question requirements? Are my Hitdice and Class structures correct? If not, how would one do this?
 
Last edited by a moderator:
Technology news on Phys.org
You have defined MAX_STAT as null. That may cause a compile error, and failing that, it would definitely cause a run time memory overrun.
Also, this works:
const char *paStatsLabels[] = { "Level", "Str", ...
 
You created an enum for the various attributes (good idea), but then you didn't use it! Instead, you used integer constants, e.g. stats_label[0], and not even in the same order as the enum. Also, you used the magic number 7 for the upper bound in the for loop, when you could have used MAX_STAT, which would have made your code more maintainable if someone added a new stat.

Also, since each stat from STR through CHA has an associated bonus, consider bundling the stat with the bonus into a struct:

Code:
struct StatWithBonus
{
    int stat;
    int bonus;
};

and making an array of these instead of separate arrays for stat and bonus.
 

Similar threads

Replies
7
Views
2K
  • · Replies 5 ·
Replies
5
Views
4K
Replies
3
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 6 ·
Replies
6
Views
11K
Replies
47
Views
5K
  • · Replies 33 ·
2
Replies
33
Views
7K
  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 5 ·
Replies
5
Views
2K