Completed the conversion to the new linked-list type.

- Moved all code relating to skills to use the new linked-lists.
- Removed all old code relating to other lists.
- Improved linked lists to get nodes more efficiently in the second half of the list.
This commit is contained in:
Barry Kane 2022-11-29 21:04:36 +00:00
parent 51f1a953e7
commit 4cc0d3a0f6
6 changed files with 86 additions and 173 deletions

View File

@ -468,13 +468,15 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
bzero(statMessage->messageContent, sizeof(char) * MAX); bzero(statMessage->messageContent, sizeof(char) * MAX);
if(currentCommand->caller->skills->head != NULL) if(currentCommand->caller->skills->head != NULL)
{ {
skillNode * currentSkill = currentCommand->caller->skills->head; size_t skillIndex = 0;
int charCount = 0; int charCount = 0;
bool addNewline = false; bool addNewline = false;
while(currentSkill != NULL) playerSkill * skill;
while(skillIndex < currentCommand->caller->skills->itemCount)
{ {
snprintf(formattedString, 120, "| %2d | %31s ", skill = getFromList(currentCommand->caller->skills, skillIndex)->skill;
currentSkill->skill->skillPoints, currentSkill->skill->skillName); skillIndex++;
snprintf(formattedString, 120, "| %2d | %31s ", skill->skillPoints, skill->skillName);
charCount += 43; charCount += 43;
strncat(statMessage->messageContent, formattedString, 120); strncat(statMessage->messageContent, formattedString, 120);
if((charCount + 43) >= MAX) if((charCount + 43) >= MAX)
@ -495,8 +497,6 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
{ {
addNewline = true; addNewline = true;
} }
currentSkill = currentSkill->next;
} }
queueTargetedOutputMessage(parameters->outputQueue, statMessage, &currentCommand->caller, 1); queueTargetedOutputMessage(parameters->outputQueue, statMessage, &currentCommand->caller, 1);
} }
@ -617,14 +617,16 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
} }
if(strncmp(currentCommand->command, "listskills", 10) == 0) if(strncmp(currentCommand->command, "listskills", 10) == 0)
{ {
skillNode * currentSkill = parameters->globalSkillList->head;
userMessage * listMessage = calloc(1, sizeof(userMessage)); userMessage * listMessage = calloc(1, sizeof(userMessage));
char * formattedString = calloc(121, sizeof(char)); char * formattedString = calloc(121, sizeof(char));
int charCount = 0; int charCount = 0;
size_t skillIndex = 0;
bool addNewline = false; bool addNewline = false;
while(currentSkill != NULL) playerSkill * currentSkill;
while(skillIndex < parameters->globalSkillList->itemCount)
{ {
snprintf(formattedString, 120, "| %-31s ", currentSkill->skill->skillName); currentSkill = getFromList(parameters->globalSkillList, skillIndex)->skill;
snprintf(formattedString, 120, "| %-31s ", currentSkill->skillName);
charCount += 43; charCount += 43;
strncat(listMessage->messageContent, formattedString, 120); strncat(listMessage->messageContent, formattedString, 120);
if((charCount + 46) >= MAX) if((charCount + 46) >= MAX)
@ -644,7 +646,7 @@ int evaluateNextCommand(gameLogicParameters * parameters, commandQueue * queue)
{ {
addNewline = true; addNewline = true;
} }
currentSkill = currentSkill->next; skillIndex++;
} }
queueTargetedOutputMessage(parameters->outputQueue, listMessage, &currentCommand->caller, 1); queueTargetedOutputMessage(parameters->outputQueue, listMessage, &currentCommand->caller, 1);
free(listMessage); free(listMessage);
@ -727,7 +729,7 @@ outcome statCheck(playerInfo * player, int chance, coreStat statToCheck)
} }
// Run a skill check: // Run a skill check:
outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t skillNameLength, skillList * globalSkillList) outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t skillNameLength, list * globalSkillList)
{ {
// Calculate the chance: // Calculate the chance:
if(chance > 100 || chance < 0) if(chance > 100 || chance < 0)
@ -738,35 +740,28 @@ outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t ski
// Check if the player has the given skill: // Check if the player has the given skill:
bool playerHasSkill = false; bool playerHasSkill = false;
skillNode * currentPlayerNode = player->skills->head; size_t playerIndex = 0;
while(currentPlayerNode != NULL) while(playerIndex < player->skills->itemCount)
{ {
if(strncmp(skillName, currentPlayerNode->skill->skillName, skillNameLength) == 0) if(strncmp(skillName, getFromList(player->skills, playerIndex)->skill->skillName, skillNameLength) != 0)
{ {
playerHasSkill = true; playerHasSkill = true;
break; break;
} }
currentPlayerNode = currentPlayerNode->next; playerIndex++;
} }
// If the player doesn't have the skill, check if it's in the game and is trained: // If the player doesn't have the skill, check if it's in the game and is trained:
bool trainedSkill = false; bool trainedSkill = false;
if(!playerHasSkill) size_t globalIndex = 0;
while(globalIndex < globalSkillList->itemCount)
{ {
skillNode * currentNode = globalSkillList->head; if(strncmp(skillName, getFromList(globalSkillList, globalIndex)->skill->skillName, skillNameLength) != 0)
while(strncmp(skillName, currentNode->skill->skillName, 32) != 0)
{ {
if(currentNode->next == NULL) trainedSkill = getFromList(globalSkillList, globalIndex)->skill->trainedSkill;
{ break;
fprintf(stderr, "Skill doesn't exist in skill list.\n");
return ERROR;
}
currentNode = currentNode->next;
}
if(currentNode->skill->trainedSkill == true)
{
trainedSkill = true;
} }
globalIndex++;
} }
// Calculate the modifier: // Calculate the modifier:
@ -775,9 +770,9 @@ outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t ski
{ {
modifier = -100; modifier = -100;
} }
else else if(playerHasSkill)
{ {
modifier = currentPlayerNode->skill->skillPoints * 4; modifier = getFromList(player->skills, playerIndex)->skill->skillModifier * 4;
} }
// Attempt the check: // Attempt the check:

View File

@ -20,7 +20,7 @@ typedef struct gameLogicParameters
playerInfo * connectedPlayers; playerInfo * connectedPlayers;
inputMessageQueue * inputQueue; inputMessageQueue * inputQueue;
outputMessageQueue * outputQueue; outputMessageQueue * outputQueue;
skillList * globalSkillList; list * globalSkillList;
} gameLogicParameters; } gameLogicParameters;
// Thread function which runs the main game loop, given the needed parameters: // Thread function which runs the main game loop, given the needed parameters:
@ -90,6 +90,6 @@ typedef enum outcome
outcome statCheck(playerInfo * player, int chance, coreStat statToCheck); outcome statCheck(playerInfo * player, int chance, coreStat statToCheck);
// Run a skill check: // Run a skill check:
outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t skillNameLength, skillList * globalSkillList); outcome skillCheck(playerInfo * player, int chance, char * skillName, size_t skillNameLength, list * globalSkillList);
#endif #endif

View File

@ -120,6 +120,17 @@ listNode * getNodeFromList(list * list, size_t listIndex)
} }
// Loop through the entries in the list until we get to the right one: // Loop through the entries in the list until we get to the right one:
else else
{
if((list->itemCount / 2) < listIndex)
{
listNode * currentNode = list->tail;
while(listIndex-- > 0)
{
currentNode = currentNode->previous;
}
return currentNode;
}
else
{ {
listNode * currentNode = list->head; listNode * currentNode = list->head;
while(listIndex-- > 0) while(listIndex-- > 0)
@ -128,6 +139,7 @@ listNode * getNodeFromList(list * list, size_t listIndex)
} }
return currentNode; return currentNode;
} }
}
} }
// Adds the given data to the end of a list: // Adds the given data to the end of a list:

View File

@ -9,12 +9,12 @@
#include "playerdata.h" #include "playerdata.h"
// Create a new skill and add it to the global skill list: // Create a new skill and add it to the global skill list:
int createSkill(skillList * globalSkillList, char * skillName, int skillNameLength, bool trainedSkill) listNode * createSkill(list * globalSkillList, char * skillName, int skillNameLength, bool trainedSkill)
{ {
if(skillNameLength >= 32) if(skillNameLength >= 32)
{ {
fprintf(stderr, "Skill name is too long. Please shorten the name and try again.\n"); fprintf(stderr, "Skill name is too long. Please shorten the name and try again.\n");
return -1; return NULL;
} }
playerSkill * newSkill = malloc(sizeof(playerSkill)); playerSkill * newSkill = malloc(sizeof(playerSkill));
@ -26,112 +26,56 @@ int createSkill(skillList * globalSkillList, char * skillName, int skillNameLeng
newSkill->trainedSkill = trainedSkill; newSkill->trainedSkill = trainedSkill;
// Add the skill to a node in the list: // Add the skill to a node in the list:
return(addSkillNode(globalSkillList, newSkill)); return(addToList(globalSkillList, newSkill, SKILL));
}
// Add a skill node to a skill list:
int addSkillNode(skillList * skillList, playerSkill * skill)
{
if(skillList->head == NULL)
{
skillList->head = malloc(sizeof(skillNode));
skillList->head->skill = skill;
skillList->head->next = NULL;
skillList->skillCount = 1;
return 0;
}
else
{
skillNode * currentNode = skillList->head;
while(currentNode->next != NULL)
{
currentNode = currentNode->next;
}
currentNode->next = malloc(sizeof(skillNode));
currentNode->next->skill = skill;
currentNode->next->next = NULL;
skillList->skillCount++;
return skillList->skillCount;
}
}
// Remove a skill node from a skill list:
int removeSkillNode(skillList * skillList, playerSkill * skill)
{
// Check the validity of the pointers:
if(skillList->head == NULL || skill == NULL)
{
return -1;
}
if(skillList->head->skill == skill)
{
skillNode * newHead = skillList->head->next;
free(skillList->head->skill);
free(skillList->head);
skillList->head = newHead;
return 0;
}
else
{
skillNode * currentNode = skillList->head;
skillNode * previousNode = skillList->head;
while(currentNode->skill != skill)
{
if(currentNode->next == NULL)
{
return -1;
}
previousNode = currentNode;
currentNode = currentNode->next;
}
free(currentNode->skill);
previousNode->next = currentNode->next;
free(currentNode);
return 0;
}
} }
// Take a skill and add it to the player's skill list: // Take a skill and add it to the player's skill list:
int takeSkill(skillList * globalSkillList, char * skillName, int skillNameLength, playerInfo * targetPlayer) int takeSkill(list * globalSkillList, char * skillName, int skillNameLength, playerInfo * targetPlayer)
{ {
// Check if the skill exists in the game:
skillNode * currentNode = globalSkillList->head; size_t globalIndex = 0;
while(strncmp(skillName, currentNode->skill->skillName, 32) != 0) bool skillExists = false;
while(globalIndex < globalSkillList->itemCount)
{ {
if(currentNode->next == NULL) 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"); fprintf(stderr, "Skill doesn't exist in skill list.\n");
return -1; return -1;
} }
currentNode = currentNode->next;
}
// Check if the player has the skill:
size_t playerIndex = 0;
bool playerHasSkill = false; bool playerHasSkill = false;
skillNode * currentPlayerNode = targetPlayer->skills->head; while(playerIndex < targetPlayer->skills->itemCount)
while(currentPlayerNode != NULL)
{ {
if(strncmp(skillName, currentPlayerNode->skill->skillName, skillNameLength) == 0) if(strncmp(skillName, getFromList(targetPlayer->skills, playerIndex)->skill->skillName, skillNameLength) == 0)
{ {
playerHasSkill = true; playerHasSkill = true;
break; break;
} }
currentPlayerNode = currentPlayerNode->next; playerIndex++;
} }
if(playerHasSkill) if(playerHasSkill)
{ {
currentPlayerNode->skill->skillPoints++; getFromList(targetPlayer->skills, playerIndex)->skill->skillPoints++;
} }
// Copy the skill into the player's skill list:
else else
{ {
addSkillNode(targetPlayer->skills, currentNode->skill); playerSkill * newSkill = calloc(1, sizeof(playerSkill));
currentPlayerNode = targetPlayer->skills->head; strncpy(newSkill->skillName, getFromList(globalSkillList, globalIndex)->skill->skillName, 32);
while(currentPlayerNode->next != NULL) printf("%s ", newSkill->skillName);
{ newSkill->skillPoints = 1;
currentPlayerNode = currentPlayerNode->next; addToList(targetPlayer->skills, newSkill, SKILL);
}
currentPlayerNode->skill->skillPoints = 1;
} }
return 0; return 0;
} }
@ -268,25 +212,7 @@ coreStat getCoreStatFromString(char * inputString, int stringLength)
int deallocatePlayer(playerInfo * playerToDeallocate) int deallocatePlayer(playerInfo * playerToDeallocate)
{ {
// Deallocate the skill list: // Deallocate the skill list:
if(playerToDeallocate->skills->skillCount > 0) destroyList(&(playerToDeallocate->skills));
{
// Allocate enough pointers:
skillNode * nodesToDeallocate[playerToDeallocate->skills->skillCount];
skillNode * currentSkillNode = playerToDeallocate->skills->head;
// Get a list of all the nodes together:
for(int index = 0; index < playerToDeallocate->skills->skillCount; index++)
{
nodesToDeallocate[index] = currentSkillNode;
currentSkillNode = currentSkillNode->next;
}
// Deallocate all the nodes:
for(int index = 0; index < playerToDeallocate->skills->skillCount; index++)
{
free(nodesToDeallocate[index]);
}
}
// Deallocate the stat block: // Deallocate the stat block:
free(playerToDeallocate->stats); free(playerToDeallocate->stats);

View File

@ -11,6 +11,8 @@
// Let the compiler know there will be structs defined elsewhere: // Let the compiler know there will be structs defined elsewhere:
typedef struct playerPath playerPath; typedef struct playerPath playerPath;
typedef struct playerArea playerArea; typedef struct playerArea playerArea;
typedef struct list list;
typedef struct listNode listNode;
typedef struct statBlock typedef struct statBlock
{ {
@ -42,25 +44,12 @@ typedef struct playerSkill
bool trainedSkill; bool trainedSkill;
} playerSkill; } playerSkill;
typedef struct skillNode skillNode;
struct skillNode
{
playerSkill * skill;
skillNode * next;
};
typedef struct skillList
{
skillNode * head;
int skillCount;
} skillList;
typedef struct playerInfo typedef struct playerInfo
{ {
char playerName[32]; char playerName[32];
playerArea * currentArea; playerArea * currentArea;
statBlock * stats; statBlock * stats;
skillList * skills; list * skills;
} playerInfo; } playerInfo;
typedef enum coreStat typedef enum coreStat
@ -74,18 +63,11 @@ typedef enum coreStat
} coreStat; } coreStat;
// Create a new skill and add it to the global skill list: // Create a new skill and add it to the global skill list:
int createSkill(skillList * globalSkillList, char * skillName, int skillNameLength, bool trainedSkill); listNode * createSkill(list * globalSkillList, char * skillName, int skillNameLength, bool trainedSkill);
// Add a skill node to a skill list:
int addSkillNode(skillList * skillList, playerSkill * skill);
// Remove a skill node from a skill list:
int removeSkillNode(skillList * skillList, playerSkill * skill);
int removeSkillByID(skillList * skillList, playerSkill * skill);
// Take a skill and add it to the player's skill list: // Take a skill and add it to the player's skill list:
int takeSkill(skillList * globalSkillList, char * skillName, int skillNameLength, playerInfo * targetPlayer); int takeSkill(list * globalSkillList, char * skillName, int skillNameLength, playerInfo * targetPlayer);
int takeSkillbyID(skillList * globalSkillList, int skillID, playerInfo * targetPlayer); int takeSkillbyID(list * globalSkillList, int skillID, playerInfo * targetPlayer);
// Take a string containing a core stat name and return the core stat: // Take a string containing a core stat name and return the core stat:
coreStat getCoreStatFromString(char * string, int stringLength); coreStat getCoreStatFromString(char * string, int stringLength);

View File

@ -94,8 +94,7 @@ int main(int argc, char ** argv)
createOneWayPath(getFromList(areas, 2)->area, getFromList(areas, 3)->area, createOneWayPath(getFromList(areas, 2)->area, getFromList(areas, 3)->area,
"Continue to station interior. "); "Continue to station interior. ");
skillList * globalSkillList = malloc(sizeof(skillList)); list * globalSkillList = createList(SKILL);
globalSkillList->head = NULL;
// Create a few basic skills: // Create a few basic skills:
createSkill(globalSkillList, "Medicine", 8, true); createSkill(globalSkillList, "Medicine", 8, true);
@ -116,8 +115,7 @@ int main(int argc, char ** argv)
connectedPlayers[index].stats = calloc(1, sizeof(statBlock)); connectedPlayers[index].stats = calloc(1, sizeof(statBlock));
connectedPlayers[index].stats->specPoints = 30; connectedPlayers[index].stats->specPoints = 30;
connectedPlayers[index].stats->skillPoints = 30; connectedPlayers[index].stats->skillPoints = 30;
connectedPlayers[index].skills = calloc(1, sizeof(skillList)); connectedPlayers[index].skills = createList(SKILL);
connectedPlayers[index].skills->head = NULL;
} }
// -==[ TEST GAME-STATE INITIALIZATION END ]==- // -==[ TEST GAME-STATE INITIALIZATION END ]==-