225 lines
4.8 KiB
C
225 lines
4.8 KiB
C
// playerdata.c: Contains functions definitions for working with player data.
|
|
// Barry Kane, 2021
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include "constants.h"
|
|
#include "playerdata.h"
|
|
|
|
// Create a new skill and add it to the global skill list:
|
|
listNode * createSkill(list * globalSkillList, char * skillName, int skillNameLength, bool trainedSkill)
|
|
{
|
|
if(skillNameLength >= 32)
|
|
{
|
|
fprintf(stderr, "Skill name is too long. Please shorten the name and try again.\n");
|
|
return NULL;
|
|
}
|
|
playerSkill * newSkill = malloc(sizeof(playerSkill));
|
|
|
|
strncpy(newSkill->skillName, skillName, 31);
|
|
newSkill->skillName[31] = '\0';
|
|
|
|
newSkill->skillPoints = 0;
|
|
newSkill->skillModifier = 0;
|
|
newSkill->trainedSkill = trainedSkill;
|
|
|
|
// Add the skill to a node in the list:
|
|
return(addToList(globalSkillList, newSkill, SKILL));
|
|
}
|
|
|
|
// Take a skill and add it to the player's skill list:
|
|
int takeSkill(list * globalSkillList, char * skillName, int skillNameLength, playerInfo * targetPlayer)
|
|
{
|
|
// Check if the skill exists in the game:
|
|
size_t globalIndex = 0;
|
|
bool skillExists = false;
|
|
while(globalIndex < globalSkillList->itemCount)
|
|
{
|
|
if(strncmp(skillName, getFromList(globalSkillList, globalIndex)->skill->skillName, skillNameLength) == 0)
|
|
{
|
|
skillExists = true;
|
|
break;
|
|
}
|
|
globalIndex++;
|
|
}
|
|
|
|
if(!skillExists)
|
|
{
|
|
fprintf(stderr, "Skill doesn't exist in skill list.\n");
|
|
return -1;
|
|
}
|
|
|
|
// Check if the player has the skill:
|
|
size_t playerIndex = 0;
|
|
bool playerHasSkill = false;
|
|
while(playerIndex < targetPlayer->skills->itemCount)
|
|
{
|
|
if(strncmp(skillName, getFromList(targetPlayer->skills, playerIndex)->skill->skillName, skillNameLength) == 0)
|
|
{
|
|
playerHasSkill = true;
|
|
break;
|
|
}
|
|
playerIndex++;
|
|
}
|
|
if(playerHasSkill)
|
|
{
|
|
getFromList(targetPlayer->skills, playerIndex)->skill->skillPoints++;
|
|
}
|
|
|
|
// Copy the skill into the player's skill list:
|
|
else
|
|
{
|
|
playerSkill * newSkill = calloc(1, sizeof(playerSkill));
|
|
strncpy(newSkill->skillName, getFromList(globalSkillList, globalIndex)->skill->skillName, 32);
|
|
printf("%s ", newSkill->skillName);
|
|
newSkill->skillPoints = 1;
|
|
addToList(targetPlayer->skills, newSkill, SKILL);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Take a string containing a core stat name and return the core stat:
|
|
coreStat getCoreStatFromString(char * inputString, int stringLength)
|
|
{
|
|
// Check we've got a long enough string to fit a stat:
|
|
if(stringLength < 4)
|
|
{
|
|
return INVALID;
|
|
}
|
|
|
|
// Lowercase the string:
|
|
char * string = malloc(sizeof(char) * stringLength);
|
|
for(int index = 0; index < stringLength; index++)
|
|
{
|
|
string[index] = tolower(inputString[index]);
|
|
}
|
|
|
|
// If we have a string that's at most just the stat name plus a null character, or
|
|
// a dirtier string, we can check in a better order and ignore impossibilites:
|
|
if(stringLength < 9)
|
|
{
|
|
if(stringLength <= 4)
|
|
{
|
|
if(strncmp(string, "wits", 4) == 0)
|
|
{
|
|
free(string);
|
|
return WITS;
|
|
}
|
|
else
|
|
{
|
|
free(string);
|
|
return INVALID;
|
|
}
|
|
}
|
|
// Hopefully one of the seven letter long ones:
|
|
else if(stringLength <= 7)
|
|
{
|
|
if(strncmp(string, "strength", 7) == 0)
|
|
{
|
|
free(string);
|
|
return STRENGTH;
|
|
}
|
|
else if(strncmp(string, "dexerity", 7) == 0)
|
|
{
|
|
free(string);
|
|
return DEXERITY;
|
|
}
|
|
if(strncmp(string, "wits", 4) == 0)
|
|
{
|
|
free(string);
|
|
return WITS;
|
|
}
|
|
else
|
|
{
|
|
free(string);
|
|
return INVALID;
|
|
}
|
|
}
|
|
// Hopefully one of the 8 letter long stats:
|
|
else
|
|
{
|
|
if(strncmp(string, "intellect", 8) == 0)
|
|
{
|
|
free(string);
|
|
return INTELLECT;
|
|
}
|
|
else if(strncmp(string, "endurance", 8) == 0)
|
|
{
|
|
free(string);
|
|
return ENDURANCE;
|
|
}
|
|
else if(strncmp(string, "strength", 7) == 0)
|
|
{
|
|
free(string);
|
|
return STRENGTH;
|
|
}
|
|
else if(strncmp(string, "dexerity", 7) == 0)
|
|
{
|
|
free(string);
|
|
return DEXERITY;
|
|
}
|
|
if(strncmp(string, "wits", 4) == 0)
|
|
{
|
|
free(string);
|
|
return WITS;
|
|
}
|
|
else
|
|
{
|
|
free(string);
|
|
return INVALID;
|
|
}
|
|
}
|
|
}
|
|
// Worst case, it's definitely a dirty string, compare them all:
|
|
else
|
|
{
|
|
if(strncmp(string, "wits", 4) == 0)
|
|
{
|
|
free(string);
|
|
return WITS;
|
|
}
|
|
else if(strncmp(string, "intellect", 8) == 0)
|
|
{
|
|
free(string);
|
|
return INTELLECT;
|
|
}
|
|
else if(strncmp(string, "strength", 7) == 0)
|
|
{
|
|
free(string);
|
|
return STRENGTH;
|
|
}
|
|
else if(strncmp(string, "endurance", 8) == 0)
|
|
{
|
|
free(string);
|
|
return ENDURANCE;
|
|
}
|
|
else if(strncmp(string, "dexerity", 7) == 0)
|
|
{
|
|
free(string);
|
|
return DEXERITY;
|
|
}
|
|
else
|
|
{
|
|
free(string);
|
|
return INVALID;
|
|
}
|
|
}
|
|
}
|
|
|
|
int deallocatePlayer(playerInfo * playerToDeallocate)
|
|
{
|
|
// Deallocate the skill list:
|
|
destroyList(&(playerToDeallocate->skills));
|
|
|
|
// Deallocate the stat block:
|
|
free(playerToDeallocate->stats);
|
|
|
|
// Deallocate the player:
|
|
free(playerToDeallocate);
|
|
|
|
return 0;
|
|
}
|