From 85dc8f5823a0ceecaf37cb1a06081807557ecdd4 Mon Sep 17 00:00:00 2001 From: HarryNews Date: Mon, 11 Jul 2016 12:27:22 -0400 Subject: [PATCH 01/18] Create proposal.md --- proposal.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 proposal.md diff --git a/proposal.md b/proposal.md new file mode 100644 index 0000000..b691287 --- /dev/null +++ b/proposal.md @@ -0,0 +1,6 @@ +##Overview +This will be a text adventure where the player "watches" an event unfold from a security camera. They will not have any control over the events, but they might have a say in the futures of those involved. It will be more of an interactive story than an actual game. +##How I'll do it +The story will be input via several text files, one for each camera. Each message will be read to a "message" data type, which will store the string in question, in addition to the delay between the message and the one before it. The messages will be stored in an array which will be slowly iterated through (the iteration will have to wait for the delays) and printed. +##Reasons +I picked this project because I initially became interested in programming because I wanted to make a text adventure, and nothing seems like a better challenge than making a string-based game in c. The idea of several stories occurring at once and affecting each other also interests me, and I want to explore that in the game. I also like games that have to be played through several times to get the full story, so that's why I decided on making this. From 08290e770068657c7cd4ab1603352fa6611fe06b Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 14 Jul 2016 11:57:01 -0400 Subject: [PATCH 02/18] Buffering doesn't work! --- Cameras/cam1.txt | 3 ++ Cameras/cam2.txt | 0 Cameras/start.txt | 12 +++++ textAdventure.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 Cameras/cam1.txt create mode 100644 Cameras/cam2.txt create mode 100644 Cameras/start.txt create mode 100644 textAdventure.c diff --git a/Cameras/cam1.txt b/Cameras/cam1.txt new file mode 100644 index 0000000..85efb8a --- /dev/null +++ b/Cameras/cam1.txt @@ -0,0 +1,3 @@ +0:0:1] Hello +0:0:2] World! +0:0:3] end diff --git a/Cameras/cam2.txt b/Cameras/cam2.txt new file mode 100644 index 0000000..e69de29 diff --git a/Cameras/start.txt b/Cameras/start.txt new file mode 100644 index 0000000..34b4544 --- /dev/null +++ b/Cameras/start.txt @@ -0,0 +1,12 @@ +0:0:0] Hello! +0:0:1] 1 second +0:0:2] 2 seconds +0:0:3] 3 seconds +0:0:4] 4 seconds +0:0:5] 5 seconds +0:0:6] 6 seconds +0:0:7] 7 seconds +0:0:8] 8 seconds +0:0:9] 9 seconds +0:0:10] 10 seconds +_end diff --git a/textAdventure.c b/textAdventure.c new file mode 100644 index 0000000..99091f7 --- /dev/null +++ b/textAdventure.c @@ -0,0 +1,110 @@ +#include +#include +#include +/* Have to use #define because using a const throws an error about variables +being used in array initializers.*/ +#define MAX_MESSAGE_LENGTH 256 +/* 3 digits for hours, 2 for minutes, 2 for seconds, 2 for colons, 1 for a +square bracket, and 1 for a space */ +#define MAX_COMMAND_LENGTH 256 + +typedef struct message{ + char str[MAX_MESSAGE_LENGTH]; + /* "time" was already being used somewhere */ + unsigned int seconds; +}Message; + + + +void handlePlayerCommand(char* command, FILE* fin){ + char arg[25]; /* No command has more than one arg */ + if(sscanf(command, "help")){ + + }else if(sscanf(command, "camera %s", arg)){ + + }else if(sscanf(command, "quit")){ + + }else{ + printf("Command not recognised. Type \"help\" for a list of commands\n"); + } +} + +/* Prevents the program from continuing for a certain amount of seconds */ +void delay(unsigned int seconds){ + unsigned int start = time(0); + while(time(0) - start < seconds); +} + +int readNextLine(FILE* fin, int* prevMessageTime){ + char input[MAX_MESSAGE_LENGTH]; + unsigned int hours, minutes, seconds; + // fgets(command, MAX_COMMAND_LENGTH, fin); + + //char command[256]; + //fgets(command, 256, fin); + + //if(strstr(command, "_end") != NULL)return 0; + if(fscanf(fin, "%u:%u:%u] ", &hours, &minutes, &seconds) == 3){ + + minutes += hours * 60; + seconds += minutes * 60; + int relativeDelay = seconds - *prevMessageTime; + *prevMessageTime = seconds; + delay(relativeDelay); + char nextChar = fgetc(fin); + while(nextChar != '\n' && nextChar != '\0' && nextChar != EOF){ + printf("%c", nextChar); + nextChar = fgetc(fin); + } + printf("\n"); + //printf("\n"); + }else if(strstr(fgets(input, MAX_MESSAGE_LENGTH, fin), "_end") != NULL){ + return 0; + } + + return 1; +} + + + +int main(){ + + int inputBuffLen = 20; + char inputBuff[inputBuffLen]; + memset(inputBuff, '\0', inputBuffLen); + printf("Buffer success? %d\n", setvbuf(stdin, inputBuff, _IOLBF, inputBuffLen)); + + // int length = 1024; + // Message messages[length]; + // readFile(messages, &length); + + FILE* fin = fopen("./Cameras/start.txt", "r"); + int prevMessageTime = 0; + while(readNextLine(fin, &prevMessageTime)){ + // for(int i = 0; i < inputBuffLen; i++) printf("%d, ", inputBuff[i]); + // printf("\n"); + while(strlen(inputBuff) > 0){ /* If the user is inputting something */ + char playerInput[inputBuffLen]; + scanf("%s", playerInput); + handlePlayerCommand(playerInput, fin); + } + } + + + // for(int i = 0; i < length; i++){ + // printf("Time: %u, Message: %s\n", messages[i].seconds, messages[i].str); + // + // if(strlen(inputBuff) > 0){ /* If the user is inputting something */ + // char playerInput[inputBuffLen]; + // scanf("%s", playerInput); + // handleCommand(playerInput); + // } + // + // if(i + 1 < length) + // delay(messages[i + 1].seconds - messages[i].seconds); + // } + + fclose(fin); + return 0; +} +//FILE* fin = fopen("./Cameras/exampleCam.txt", "r"); From 053e8e61f07e84aed47171c353c082fb725b1e9b Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 14 Jul 2016 15:45:50 -0400 Subject: [PATCH 03/18] It works now! --- Cameras/cam1.txt | 6 +- Cameras/cam2.txt | 0 Cameras/start.txt | 13 +---- Cameras/test2.txt | 11 ++++ textAdventure.c | 145 +++++++++++++++++++++++++++------------------- 5 files changed, 100 insertions(+), 75 deletions(-) delete mode 100644 Cameras/cam2.txt create mode 100644 Cameras/test2.txt diff --git a/Cameras/cam1.txt b/Cameras/cam1.txt index 85efb8a..911e299 100644 --- a/Cameras/cam1.txt +++ b/Cameras/cam1.txt @@ -1,3 +1,3 @@ -0:0:1] Hello -0:0:2] World! -0:0:3] end +1] Hello and welcome to sensational news! +1] Shit I'm out of content! +_exit diff --git a/Cameras/cam2.txt b/Cameras/cam2.txt deleted file mode 100644 index e69de29..0000000 diff --git a/Cameras/start.txt b/Cameras/start.txt index 34b4544..c06fe82 100644 --- a/Cameras/start.txt +++ b/Cameras/start.txt @@ -1,12 +1,3 @@ -0:0:0] Hello! -0:0:1] 1 second -0:0:2] 2 seconds -0:0:3] 3 seconds -0:0:4] 4 seconds -0:0:5] 5 seconds -0:0:6] 6 seconds -0:0:7] 7 seconds -0:0:8] 8 seconds -0:0:9] 9 seconds -0:0:10] 10 seconds +1] Hello! +2] Welcome to the text adventure! _end diff --git a/Cameras/test2.txt b/Cameras/test2.txt new file mode 100644 index 0000000..603964b --- /dev/null +++ b/Cameras/test2.txt @@ -0,0 +1,11 @@ +1] b 0 seconds +1] b 1 second +1] b 2 seconds +1] b 3 seconds +1] b 4 seconds +1] b 5 seconds +1] b 6 seconds +1] b 7 seconds +1] b 8 seconds +1] b 9 seconds +_end diff --git a/textAdventure.c b/textAdventure.c index 99091f7..ce5766a 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include /* Have to use #define because using a const throws an error about variables being used in array initializers.*/ #define MAX_MESSAGE_LENGTH 256 @@ -8,25 +10,52 @@ being used in array initializers.*/ square bracket, and 1 for a space */ #define MAX_COMMAND_LENGTH 256 -typedef struct message{ - char str[MAX_MESSAGE_LENGTH]; - /* "time" was already being used somewhere */ - unsigned int seconds; -}Message; - - +struct threadVars{ /* struct because I can only pass one argument to the threads */ + unsigned int* gameTime; + FILE** finptr; /* double pointer because inputThread might change the file */ + int* stopPrinting; +}; + +/* If there exists a file named "Cameras/.txt", will switch fin to that, +move the buffer to the first message that comes chronologically after +previousMessageTime, and returns 1. If the file doesn't exist, returns 0 */ +int switchCamera(char* name, struct threadVars* vars){ + char path[50]; + sprintf(path, "./Cameras/%s.txt", name); + FILE* open = fopen(path, "r"); + if(open == NULL) return 0; + fclose(*(vars->finptr)); + *(vars->finptr) = open; + int skipTime = 0; + int lineDelay; + char nextLine[MAX_MESSAGE_LENGTH]; + while(skipTime < *(vars->gameTime) && fgets(nextLine, MAX_MESSAGE_LENGTH, *(vars->finptr))){ + sscanf(nextLine, "%d]", &lineDelay); + printf("skiptime: %d gametime: %u. skip!\n", skipTime, *(vars->gameTime)); + skipTime += lineDelay; + } + return 1; +} -void handlePlayerCommand(char* command, FILE* fin){ +int handlePlayerCommand(char* command, struct threadVars* vars){ char arg[25]; /* No command has more than one arg */ - if(sscanf(command, "help")){ - - }else if(sscanf(command, "camera %s", arg)){ - - }else if(sscanf(command, "quit")){ - + if(strcmp(command, "\n") == 0){ + *(vars->stopPrinting) = !*(vars->stopPrinting); + }else if(strstr(command, "help") != NULL){ + printf("To switch cameras, type \"camera\"\n\ + To restart, type \"restart\"\n\ + To quit, type \"quit\"\n"); + }else if(strstr(command, "camera") != NULL){ + if(sscanf(command, "camera %s", arg)){ + if(switchCamera(arg, vars)) return 1; + printf("The cameras are: start, cam1, cam2\n"); + } + }else if(strstr(command, "quit") != NULL){ + exit(0); }else{ printf("Command not recognised. Type \"help\" for a list of commands\n"); } + return 1; } /* Prevents the program from continuing for a certain amount of seconds */ @@ -35,29 +64,19 @@ void delay(unsigned int seconds){ while(time(0) - start < seconds); } -int readNextLine(FILE* fin, int* prevMessageTime){ +int readNextLine(FILE* fin, int* gameTime){ char input[MAX_MESSAGE_LENGTH]; - unsigned int hours, minutes, seconds; - // fgets(command, MAX_COMMAND_LENGTH, fin); - - //char command[256]; - //fgets(command, 256, fin); + unsigned int timeDelay; - //if(strstr(command, "_end") != NULL)return 0; - if(fscanf(fin, "%u:%u:%u] ", &hours, &minutes, &seconds) == 3){ - - minutes += hours * 60; - seconds += minutes * 60; - int relativeDelay = seconds - *prevMessageTime; - *prevMessageTime = seconds; - delay(relativeDelay); + if(fscanf(fin, "%u] ", &timeDelay)){ char nextChar = fgetc(fin); while(nextChar != '\n' && nextChar != '\0' && nextChar != EOF){ printf("%c", nextChar); nextChar = fgetc(fin); } printf("\n"); - //printf("\n"); + delay(timeDelay); + *gameTime += timeDelay; }else if(strstr(fgets(input, MAX_MESSAGE_LENGTH, fin), "_end") != NULL){ return 0; } @@ -65,43 +84,47 @@ int readNextLine(FILE* fin, int* prevMessageTime){ return 1; } +void* outputThread(void* arg){ + struct threadVars* vars = arg; + /* if stopPrinting is true, then it won't even bother checking the other side of + the ||s so readNextLine will never be executed. */ + while(*(vars->stopPrinting) || readNextLine(*(vars->finptr), vars->gameTime)); + /* because the inputThread is still waiting for input, the user needs to input a quitting command */ + printf("Game over. Please type \"restart\" or \"quit\"\n"); +} +/* Waits for player input, and then checks if it's a command and if so, executes it */ +void* inputThread(void* arg){ + struct threadVars* vars = arg; + int inputLength = 100; + char input[inputLength]; + while(handlePlayerCommand( + fgets(input, inputLength, stdin), vars) + ); +} int main(){ - - int inputBuffLen = 20; - char inputBuff[inputBuffLen]; - memset(inputBuff, '\0', inputBuffLen); - printf("Buffer success? %d\n", setvbuf(stdin, inputBuff, _IOLBF, inputBuffLen)); - - // int length = 1024; - // Message messages[length]; - // readFile(messages, &length); - + int gameTime = 0; FILE* fin = fopen("./Cameras/start.txt", "r"); - int prevMessageTime = 0; - while(readNextLine(fin, &prevMessageTime)){ - // for(int i = 0; i < inputBuffLen; i++) printf("%d, ", inputBuff[i]); - // printf("\n"); - while(strlen(inputBuff) > 0){ /* If the user is inputting something */ - char playerInput[inputBuffLen]; - scanf("%s", playerInput); - handlePlayerCommand(playerInput, fin); - } - } - - - // for(int i = 0; i < length; i++){ - // printf("Time: %u, Message: %s\n", messages[i].seconds, messages[i].str); - // - // if(strlen(inputBuff) > 0){ /* If the user is inputting something */ - // char playerInput[inputBuffLen]; - // scanf("%s", playerInput); - // handleCommand(playerInput); + int stopPrinting = 0; + struct threadVars vars = {&gameTime, &fin, &stopPrinting}; + pthread_t outpThread; + pthread_t inpThread; + pthread_create(&outpThread, NULL, outputThread, &vars); + pthread_create(&inpThread, NULL, inputThread, &vars); + pthread_join(outpThread, NULL); + pthread_join(inpThread, NULL); + // FILE* fin = fopen("./Cameras/start.txt", "r"); + // int prevMessageTime = 0; + // int inputBuffLen = 50; + // char playerInput[inputBuffLen]; + // while(readNextLine(fin, &prevMessageTime)){ + // // for(int i = 0; i < inputBuffLen; i++) printf("%d, ", inputBuff[i]); + // // printf("\n"); + // if(feof(stdin) == 0){ /* If the user is inputting something */ + // fgets(playerInput, inputBuffLen, stdin); + // handlePlayerCommand(playerInput, fin); // } - // - // if(i + 1 < length) - // delay(messages[i + 1].seconds - messages[i].seconds); // } fclose(fin); From 84311dcfaa4c565b93cf78e4f39bb70c8980a7de Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 00:40:27 -0400 Subject: [PATCH 04/18] System fully implemented --- Cameras/cam1.txt | 3 -- Cameras/delayTest.txt | 4 ++ Cameras/start.txt | 8 +++- Cameras/syntax.md | 11 +++++ Cameras/test1.txt | 21 +++++++++ Cameras/test2.txt | 30 ++++++++---- textAdventure.c | 106 ++++++++++++++++++++++-------------------- 7 files changed, 117 insertions(+), 66 deletions(-) delete mode 100644 Cameras/cam1.txt create mode 100644 Cameras/delayTest.txt create mode 100644 Cameras/syntax.md create mode 100644 Cameras/test1.txt diff --git a/Cameras/cam1.txt b/Cameras/cam1.txt deleted file mode 100644 index 911e299..0000000 --- a/Cameras/cam1.txt +++ /dev/null @@ -1,3 +0,0 @@ -1] Hello and welcome to sensational news! -1] Shit I'm out of content! -_exit diff --git a/Cameras/delayTest.txt b/Cameras/delayTest.txt new file mode 100644 index 0000000..089bdbb --- /dev/null +++ b/Cameras/delayTest.txt @@ -0,0 +1,4 @@ +d1] 1 second delay +d10] 10 second delay +d5] Will exit in 5 seconds +_end diff --git a/Cameras/start.txt b/Cameras/start.txt index c06fe82..dbfc8a9 100644 --- a/Cameras/start.txt +++ b/Cameras/start.txt @@ -1,3 +1,7 @@ -1] Hello! -2] Welcome to the text adventure! +d3] A man walks into view. He is wearing a suit, although it looks a bit too small. +s3] There is a man wearing a suit that's a bit too small for him. +d3] He clears his throat. +d3] He tightens his tie. +d2] He clears his throat again. +d3] Man: Welcome to the text adventure! _end diff --git a/Cameras/syntax.md b/Cameras/syntax.md new file mode 100644 index 0000000..0b60028 --- /dev/null +++ b/Cameras/syntax.md @@ -0,0 +1,11 @@ +#Camera Syntax +##Events +###Watching Events +To write a normal event, the syntax is "d] " +Where is the string to print and is the delay between that event and the next one +###Switching Events +Switching events are only sent if the player switches to the camera that calls them between the time it is called and the time it is called + the duration it specifies +The syntax is: "s] " +Where is the string to print and is the duration +##Exiting +To automatically exit the game, write "_exit" or "_end" at the end of the files diff --git a/Cameras/test1.txt b/Cameras/test1.txt new file mode 100644 index 0000000..e42152f --- /dev/null +++ b/Cameras/test1.txt @@ -0,0 +1,21 @@ +s10] 1s 0 seconds +d1] 1d 0 seconds +s10] 1s 1 seconds +d1] 1d 1 seconds +s10] 1s 2 seconds +d1] 1d 2 seconds +s10] 1s 3 seconds +d1] 1d 3 seconds +s10] 1s 4 seconds +d1] 1d 4 seconds +s10] 1s 5 seconds +d1] 1d 5 seconds +s10] 1s 6 seconds +d1] 1d 6 seconds +s10] 1s 7 seconds +d1] 1d 7 seconds +s10] 1s 8 seconds +d1] 1d 8 seconds +s10] 1s 9 seconds +d1] 1d 9 seconds +_end diff --git a/Cameras/test2.txt b/Cameras/test2.txt index 603964b..a8e3a80 100644 --- a/Cameras/test2.txt +++ b/Cameras/test2.txt @@ -1,11 +1,21 @@ -1] b 0 seconds -1] b 1 second -1] b 2 seconds -1] b 3 seconds -1] b 4 seconds -1] b 5 seconds -1] b 6 seconds -1] b 7 seconds -1] b 8 seconds -1] b 9 seconds +s10] 2s 0 seconds +d1] 2d 0 seconds +s10] 2s 1 seconds +d1] 2d 1 seconds +s10] 2s 2 seconds +d1] 2d 2 seconds +s10] 2s 3 seconds +d1] 2d 3 seconds +s10] 2s 4 seconds +d1] 2d 4 seconds +s10] 2s 5 seconds +d1] 2d 5 seconds +s10] 2s 6 seconds +d1] 2d 6 seconds +s10] 2s 7 seconds +d1] 2d 7 seconds +s10] 2s 8 seconds +d1] 2d 8 seconds +s10] 2s 9 seconds +d1] 2d 9 seconds _end diff --git a/textAdventure.c b/textAdventure.c index ce5766a..73b234c 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -6,101 +6,115 @@ /* Have to use #define because using a const throws an error about variables being used in array initializers.*/ #define MAX_MESSAGE_LENGTH 256 -/* 3 digits for hours, 2 for minutes, 2 for seconds, 2 for colons, 1 for a -square bracket, and 1 for a space */ -#define MAX_COMMAND_LENGTH 256 struct threadVars{ /* struct because I can only pass one argument to the threads */ - unsigned int* gameTime; + unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ FILE** finptr; /* double pointer because inputThread might change the file */ int* stopPrinting; }; /* If there exists a file named "Cameras/.txt", will switch fin to that, -move the buffer to the first message that comes chronologically after +move the stream to the first message that comes chronologically after previousMessageTime, and returns 1. If the file doesn't exist, returns 0 */ int switchCamera(char* name, struct threadVars* vars){ char path[50]; sprintf(path, "./Cameras/%s.txt", name); FILE* open = fopen(path, "r"); if(open == NULL) return 0; - fclose(*(vars->finptr)); + fclose(*(vars->finptr)); /* close the currently open file to prevent memory leaks */ *(vars->finptr) = open; int skipTime = 0; - int lineDelay; + + char nextLine[MAX_MESSAGE_LENGTH]; + /* loops until the stream is right before the first message that should be printed at or after the gameTime */ while(skipTime < *(vars->gameTime) && fgets(nextLine, MAX_MESSAGE_LENGTH, *(vars->finptr))){ - sscanf(nextLine, "%d]", &lineDelay); - printf("skiptime: %d gametime: %u. skip!\n", skipTime, *(vars->gameTime)); - skipTime += lineDelay; + int lineDelay, stringIndex; + char eventType; + sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex); + switch(eventType){ + /* if it starts with a d, it is an instant event, and because it happened in the past, + the message shouldn't print because the player didn't witness it */ + case 'd': + skipTime += lineDelay; + break; + /* if it starts with a d, it is an ongoing event, and although the player didn't + witness it starting, they still see it before it's over, so it should print */ + case 's': + if(skipTime + lineDelay >= *(vars->gameTime)) + printf("%s", nextLine + stringIndex); + break; + } + + } return 1; } -int handlePlayerCommand(char* command, struct threadVars* vars){ - char arg[25]; /* No command has more than one arg */ +/* identifies the command that the player has input and executes it.*/ +void handlePlayerCommand(char* command, struct threadVars* vars){ + /* use strcmp here because the string should consist solely of '\n' */ if(strcmp(command, "\n") == 0){ *(vars->stopPrinting) = !*(vars->stopPrinting); }else if(strstr(command, "help") != NULL){ printf("To switch cameras, type \"camera\"\n\ - To restart, type \"restart\"\n\ To quit, type \"quit\"\n"); }else if(strstr(command, "camera") != NULL){ + char arg[25]; if(sscanf(command, "camera %s", arg)){ - if(switchCamera(arg, vars)) return 1; - printf("The cameras are: start, cam1, cam2\n"); + if(switchCamera(arg, vars)) return; + /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras + the list is hardcoded because there is no platform independent way to list files as far as I know */ + printf("The cameras are: start\n"); } }else if(strstr(command, "quit") != NULL){ exit(0); }else{ printf("Command not recognised. Type \"help\" for a list of commands\n"); } - return 1; } /* Prevents the program from continuing for a certain amount of seconds */ void delay(unsigned int seconds){ unsigned int start = time(0); - while(time(0) - start < seconds); + while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; } -int readNextLine(FILE* fin, int* gameTime){ +/* Reads the next line in the stream of events +returns 1 if the program should continue, or 0 if it shouldn't*/ +int readNextLine(FILE* fin, int* gameTime, unsigned int* timeDelay){ + *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ char input[MAX_MESSAGE_LENGTH]; - unsigned int timeDelay; - - if(fscanf(fin, "%u] ", &timeDelay)){ - char nextChar = fgetc(fin); - while(nextChar != '\n' && nextChar != '\0' && nextChar != EOF){ - printf("%c", nextChar); - nextChar = fgetc(fin); - } - printf("\n"); - delay(timeDelay); - *gameTime += timeDelay; - }else if(strstr(fgets(input, MAX_MESSAGE_LENGTH, fin), "_end") != NULL){ + int stringIndex = 0; + fgets(input, MAX_MESSAGE_LENGTH, fin); + if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ + printf("%s", input + stringIndex); + delay(*timeDelay); + }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ return 0; } - return 1; } void* outputThread(void* arg){ struct threadVars* vars = arg; + /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ + int timeDelay = 0; /* if stopPrinting is true, then it won't even bother checking the other side of the ||s so readNextLine will never be executed. */ - while(*(vars->stopPrinting) || readNextLine(*(vars->finptr), vars->gameTime)); - /* because the inputThread is still waiting for input, the user needs to input a quitting command */ - printf("Game over. Please type \"restart\" or \"quit\"\n"); + while(*(vars->stopPrinting) || readNextLine(*(vars->finptr), vars->gameTime, &timeDelay)); + /* if the code reaches this point, it's time to exit! */ + printf("The end! Feel free to play again using a different camera! Exiting...\n"); + exit(0); } -/* Waits for player input, and then checks if it's a command and if so, executes it */ +/* Waits for player input and processes it */ void* inputThread(void* arg){ struct threadVars* vars = arg; int inputLength = 100; char input[inputLength]; - while(handlePlayerCommand( - fgets(input, inputLength, stdin), vars) - ); + while(1) + handlePlayerCommand(fgets(input, inputLength, stdin), vars); } int main(){ @@ -108,25 +122,15 @@ int main(){ FILE* fin = fopen("./Cameras/start.txt", "r"); int stopPrinting = 0; struct threadVars vars = {&gameTime, &fin, &stopPrinting}; + /* declare threads */ pthread_t outpThread; pthread_t inpThread; + /* create threads */ pthread_create(&outpThread, NULL, outputThread, &vars); pthread_create(&inpThread, NULL, inputThread, &vars); + /* link the threads to their return values(?) */ pthread_join(outpThread, NULL); pthread_join(inpThread, NULL); - // FILE* fin = fopen("./Cameras/start.txt", "r"); - // int prevMessageTime = 0; - // int inputBuffLen = 50; - // char playerInput[inputBuffLen]; - // while(readNextLine(fin, &prevMessageTime)){ - // // for(int i = 0; i < inputBuffLen; i++) printf("%d, ", inputBuff[i]); - // // printf("\n"); - // if(feof(stdin) == 0){ /* If the user is inputting something */ - // fgets(playerInput, inputBuffLen, stdin); - // handlePlayerCommand(playerInput, fin); - // } - // } - fclose(fin); return 0; } From 2b82d4b2b23a21f4800751240cf8ae5fb867ccec Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 01:50:17 -0400 Subject: [PATCH 05/18] Cleaned up code, wrote documentation --- textAdventure.c | 120 ++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 50 deletions(-) diff --git a/textAdventure.c b/textAdventure.c index 73b234c..54576b7 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -10,25 +10,70 @@ being used in array initializers.*/ struct threadVars{ /* struct because I can only pass one argument to the threads */ unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ FILE** finptr; /* double pointer because inputThread might change the file */ - int* stopPrinting; + int* paused; }; +/* Prevents the program from continuing for a certain amount of seconds */ +/* seconds: the amount of seconds to wait */ +void delay(unsigned int seconds){ + unsigned int start = time(0); + while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; +} + +/* Reads the next line in the stream of events */ +/* fin: the stream of events to read from */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* timeDelay: the delay, in seconds, between the previous event and the current event */ +/* returns 1 if the game should continue, or 0 if the game is over */ +int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ + *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ + char input[MAX_MESSAGE_LENGTH]; + int stringIndex = 0; + fgets(input, MAX_MESSAGE_LENGTH, fin); + if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ + printf("%s", input + stringIndex); + delay(*timeDelay); + }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ + return 0; + } + return 1; +} + +void* outputThread(void* arg){ + struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + /* store this as a pointer because it might get changed by the other thread */ + int* paused = vars->paused; + /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ + int timeDelay = 0; + /* if paused is true, then it won't even bother checking the other side of + the || so readNextLine will never be executed. */ + while(*paused || readNextLine(*finptr, gameTime, &timeDelay)); + /* if the code reaches this point, it's time to exit! */ + printf("The end! Feel free to play again using a different camera! Exiting...\n"); + exit(0); +} + /* If there exists a file named "Cameras/.txt", will switch fin to that, move the stream to the first message that comes chronologically after -previousMessageTime, and returns 1. If the file doesn't exist, returns 0 */ -int switchCamera(char* name, struct threadVars* vars){ +previousMessageTime */ +/* name: the name of the camera in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the file stream in question */ +/* returns 1 if the file exists, or 0 if it does not */ +int switchCamera(char* name, unsigned int gameTime, FILE** finptr){ char path[50]; sprintf(path, "./Cameras/%s.txt", name); FILE* open = fopen(path, "r"); if(open == NULL) return 0; - fclose(*(vars->finptr)); /* close the currently open file to prevent memory leaks */ - *(vars->finptr) = open; + fclose(*finptr); /* close the currently open file to prevent memory leaks */ + *finptr = open; int skipTime = 0; - char nextLine[MAX_MESSAGE_LENGTH]; /* loops until the stream is right before the first message that should be printed at or after the gameTime */ - while(skipTime < *(vars->gameTime) && fgets(nextLine, MAX_MESSAGE_LENGTH, *(vars->finptr))){ + while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ int lineDelay, stringIndex; char eventType; sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex); @@ -41,28 +86,33 @@ int switchCamera(char* name, struct threadVars* vars){ /* if it starts with a d, it is an ongoing event, and although the player didn't witness it starting, they still see it before it's over, so it should print */ case 's': - if(skipTime + lineDelay >= *(vars->gameTime)) + if(skipTime + lineDelay >= gameTime) printf("%s", nextLine + stringIndex); break; } - - } return 1; } /* identifies the command that the player has input and executes it.*/ -void handlePlayerCommand(char* command, struct threadVars* vars){ +/* command: the command in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the event stream that might be changed by a command */ +/* paused: boolean value representing whether or not the output is paused */ +void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused){ /* use strcmp here because the string should consist solely of '\n' */ if(strcmp(command, "\n") == 0){ - *(vars->stopPrinting) = !*(vars->stopPrinting); + *paused = !*paused; + if(*paused) + printf("Game is paused. To unpause, press enter\n"); }else if(strstr(command, "help") != NULL){ printf("To switch cameras, type \"camera\"\n\ To quit, type \"quit\"\n"); }else if(strstr(command, "camera") != NULL){ char arg[25]; if(sscanf(command, "camera %s", arg)){ - if(switchCamera(arg, vars)) return; + /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ + if(switchCamera(arg, *gameTime, finptr)) return; /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras the list is hardcoded because there is no platform independent way to list files as far as I know */ printf("The cameras are: start\n"); @@ -74,54 +124,24 @@ void handlePlayerCommand(char* command, struct threadVars* vars){ } } -/* Prevents the program from continuing for a certain amount of seconds */ -void delay(unsigned int seconds){ - unsigned int start = time(0); - while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; -} - -/* Reads the next line in the stream of events -returns 1 if the program should continue, or 0 if it shouldn't*/ -int readNextLine(FILE* fin, int* gameTime, unsigned int* timeDelay){ - *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ - char input[MAX_MESSAGE_LENGTH]; - int stringIndex = 0; - fgets(input, MAX_MESSAGE_LENGTH, fin); - if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ - printf("%s", input + stringIndex); - delay(*timeDelay); - }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ - return 0; - } - return 1; -} - -void* outputThread(void* arg){ - struct threadVars* vars = arg; - /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ - int timeDelay = 0; - /* if stopPrinting is true, then it won't even bother checking the other side of - the ||s so readNextLine will never be executed. */ - while(*(vars->stopPrinting) || readNextLine(*(vars->finptr), vars->gameTime, &timeDelay)); - /* if the code reaches this point, it's time to exit! */ - printf("The end! Feel free to play again using a different camera! Exiting...\n"); - exit(0); -} - /* Waits for player input and processes it */ void* inputThread(void* arg){ struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + int* paused = vars->paused; + int inputLength = 100; char input[inputLength]; while(1) - handlePlayerCommand(fgets(input, inputLength, stdin), vars); + handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused); } int main(){ int gameTime = 0; FILE* fin = fopen("./Cameras/start.txt", "r"); - int stopPrinting = 0; - struct threadVars vars = {&gameTime, &fin, &stopPrinting}; + int paused = 0; + struct threadVars vars = {&gameTime, &fin, &paused}; /* declare threads */ pthread_t outpThread; pthread_t inpThread; From 5ff404da7687f0514ac3f2d427ce6535b3fd3513 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 01:53:56 -0400 Subject: [PATCH 06/18] renamed README.md to README_OLD.md --- README.md => README_OLD.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.md => README_OLD.md (100%) diff --git a/README.md b/README_OLD.md similarity index 100% rename from README.md rename to README_OLD.md From d4f103a3ac536573b36e0cd93b3ba90251d1150a Mon Sep 17 00:00:00 2001 From: HarryNews Date: Fri, 15 Jul 2016 02:49:31 -0400 Subject: [PATCH 07/18] Wrote README.md --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..db65291 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +#How to play the game +The game consists of a series of messages that print out at specific times. The player interacts with the game using commands. Although not required, before writing a command, press enter to pause the messages, then write the command, then press enter again to unpause them. The commands are as follows. +### Pausing the game +To pause the game, press enter +### Changing the camera +To change the camera, type "camera " +To get a list of available cameras, type "camera" +### Listing the commands +To get a list of commands, type "help" +### Quitting +To quit, type "quit" +#How to make a game +The game runs using .txt files (which I call cameras, in this context) in the Cameras directory. When it launches, its camera will be start.txt, so that should be written first. There are 3 possible commands for a camera, which are the following. +### Witnessed Events +Witnessed events are events that only print if the player is watching the camera that the event is on when it occurs. The syntax for a witnessed event is `"d] "` where `` is the delay, in seconds, between the event in question and the event following it, and `` is the message to be sent. +### Ongoing Events +Ongoing events are events that only print if the player switches to the camera that the event is on after the event starts and before it stops. The syntax for an ongoing event is `"s] "` where `` is the time, in seconds, between the event starting and the event ending, and `` is the message to be sent +### Automatic exit +To automatically quit the program, put "_end" or "_exit" at the end of the file. +# Differences from the proposal +I originally planned to make a game, rather than just a system for the game to run on. The system was significantly more difficult than I expected, and I didn't have any time left to write the story. +# How to compile it +to compile it, use `gcc textAdventure.c -o textAdventure -lpthread` From 43d0540ce2aa9f130208750fc8c71e27dfa7a3ad Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 02:58:13 -0400 Subject: [PATCH 08/18] added compiled code --- textAdventure | Bin 0 -> 13640 bytes textAdventure.c | 30 +++++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) create mode 100755 textAdventure diff --git a/textAdventure b/textAdventure new file mode 100755 index 0000000000000000000000000000000000000000..1648b4c62e151637b9a19a16a47f4dd7af1d42d3 GIT binary patch literal 13640 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 Ut$#E>i= gameTime) - printf("%s", nextLine + stringIndex); - break; + if(sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex) == 3){ + switch(eventType){ + /* if it starts with a d, it is an instant event, and because it happened in the past, + the message shouldn't print because the player didn't witness it */ + case 'd': + skipTime += lineDelay; + break; + /* if it starts with a d, it is an ongoing event, and although the player didn't + witness it starting, they still see it before it's over, so it should print */ + case 's': + if(skipTime + lineDelay >= gameTime) + printf("%s", nextLine + stringIndex); + break; + } + }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ + printf("Camera has already ended. Quitting\n"); + exit(0); } } return 1; From 3acd281a7d9e10ab46fde3449fb7adb3d9df84d9 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 10:38:41 -0400 Subject: [PATCH 09/18] Fixed Bugs --- textAdventure | Bin 13640 -> 13640 bytes textAdventure.c | 37 ++++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/textAdventure b/textAdventure index 1648b4c62e151637b9a19a16a47f4dd7af1d42d3..d621d2d82c397ae619f9ba022c0bf7b729c28e8d 100755 GIT binary patch delta 2076 zcmZuyZERCz6n<}qu#U2R4HzHJZCUprj;(0i)C61Q%Dc!^zyc=nCBw;rGFg{Q0~9i@ z+4bfM@@8iI5c#nm6Bk`5lg=M)hiGdIru@)M5|e^6-enj@bfYLxpZDH&R^!cf&w0-| z@A-JnIlb|=c-!%W`Qk#NKNsKsG2$3-8ixU=M`s3{?2K@wXk_}yIq~y16|&~ohLgot z`}aOFvMShTIy2Xnw0j7RjkfC~)?*89FrN?tDSnh=A?`!__HH^YMg6N4>H58Nn)Xq( zcZxH@1*%91a0-#Xju3~381~P?9-6qJiD@^%Ozx#hFPBhN;+MnoU_KjRj}gI|xfOHk zxlcZpHC|vCYbUs8DcZRtt8io#Z?Tu=S2+6bq|@Jg>7(*5wEMb;$_L}@)ch6CP(>W0 zil>;$V(K^!Qwo8P8E_g^2vvM3sx&95{2lVq8ju{cW07LG)-3QC(LuPt3M}PwsI0cL z8cSLEw%qi$!U`D;@w)b9GOA&FElZuf0zm+&ix-Yi@PB}vw3GxOYlkeR*EzAATdBjR zbt{!C0P#mU(ZOnxr^0XM27K?YbhDa%FPhf})Fs#1qm{sP|VWk{wJ59*y zf4fs}DEy67Rrw92zLzJZ=&=#z;B1&ygo*UvsMT^#NB(DU?DT@_SJv_zq^MQ;43|T| z3{^I#TIjl=ELBQVg};jPYh_a zTen$dVMTyPjSTS|TH$VDNRI=vv5Z-nk%r$INphp7xRH`Is>I&$Hs661x%w$peF;5E zt)VgCRH24;Gc-}99%T$*3`0~E6EuL^zhR&-gpH8~T+*(lus^lBljkz-Pi5Q}7!U<; zjBMey!`xQjQ_g`gN(C@sh>gwIh}C!v$n@nRq3KBU0h1xxsNltCRSdxkSWiB9juhu@ z;NuydFH|BX4z{3pMI2=Nts4SOwo-IOOe)QT#y(XeG611UX98v7s*k%0VWcr&+OJsX z$#`aCcjTso=D;;P6Mdy3j90fzcP55nBJT=`iRU;0Y=b-%&;S~ZWml1_EG9wEfoggW zRMa3}{vtfzL&Ewk;QY`nB*z=1q9`c)tvO07SE4_&)}I=J_^jYVLx7kuO#mMv%{-m| z3}tGDWB;o4fi;A9H+wgE<+Ru5eQ}-YI%Fv&KC0Goy0J-~X_CKRSHpk1^6BW^JZ(F> zXWO-?%*}gQu*}OR%ON_7{~1I)%Ub*5a) z2TfVaixBU|@HYI*)2dldKj^pfL(XuiRvb+Y#Y)sQn+z|n=qyirD*+|h^p*|=q zd?B9+CC>}v!Sy9K@`Q2bEnh55;k|IVon$|a+)?()BMxFK3cg!DBM4D;q~e$fA5MpB zrI2J^*J3lD3;v9=ov!V|PB!Y=2dD1J8*o}yRkw7t#n9_z!cIcD4pKk=vq`!zN#|sZ(ccnwEzGB delta 1871 zcmZuyeQXnD7{BZISjX0OT`P0wWDD(zxXo&UGiYdar$;i}U{)9Zkj)i=`GwG#C5BW} z4s*LSPTwq9qAtWQ1}0`pCoCqcT}EipfL#Vj^$$fp;w>X#L7fGJ^Y`4fa~SWBd*1i? z{qFZX@AEu&m+DG&^`*@YC#PSI4}Of>vvy;Xwfpo%*3ORbKRLc|FF8F@cDdPI(Hs7? z$rFBc=xr`GU^=qQ<}3AaVsavFBa^&ljcql5$cNj=D<{WDL;e1irb&s=dPTZ&Thqh= zG1@;z3qCE%C*$p)8oXBUL`6ygQ#d)PUdLkgQ86kJd%V+-R8JF2N_5|y2X^LwQ3D7q zALH2Iii)aV{?@cplL1k_EJm*QM0sB-C@M=_9;777Le`sL->q1;JSm)|BpF{^Ruc`J z6_w5BMfnVJS9c;R;$-5x5kP$$YH?z!zq1X+)ht+C*?iQ9Y-HaL0#X{LT$8z!I>;wW zL-2`_<7Bw*BAq_d!Xphu>LEy>TB)OKs<<*da|toT=r;!mh(Eb&wFd*WxKU0Uw^V zO24sYOZj7auwCd<3w249yAz@u7!&2q!~f}+s0gX?o4Mll++c?+Yr@BIo;ZhbRn_Y_ z-q%z6E8C6$AoQsh`0^J<@-R+2E~Vs(F`qB{csy4 zX~pEWp(aC%>!5lQcwz`MJO+C|ZaAkvJ}iBOSf_Gp8`kNhFdC$m3!{v;Z4GB^tEoQc zmCd8Zm>ZD(nf^IWZUwkP~nI)VGlpK5krRqfJwP(Y)(mhQKQ8B5;&IMMy8OTPd6( zWELDx7!CwWs$a6E((;X;;F(jCFV|V`qlxFZKL7Ln=lrtf5BQ&Lin=OGR&xO{T1&Qd zlRUpkKG(FCz7&Px#H|8VV}qrgmc87z?XL%M>)92;H)5r|a|ubs4%qAXEuKF$Z5X?T zc};rR87QGq0oG zwEGYClEZC!W}fvrDqY(V!3_rIx7ZGto-A2bP{kK7FXZlliw^e+BKES=j#a`rtS;Wc z{CR;%jTt~L-aGII7Vt~J4G zkfoi&jIV6w8)I84uNLr)%wN5dZ^7NUs+7zBN=Ph!6>xU0oxNG@j15*_;CUN+cg_1I z{A=v4I^M_pu9ar$KV4I-!?lffvkBK5(Dk~nLbs}>zM`bq!1dFDCz&{CTDY{0b=ACR zo+~k6FPo~VF<;AxO*7te%uI7fS8r^>v!jr=v$fuOb0fYgbTzUL?<1uxxm`=C?&J=! c!`}L${7I1L1@HQz_A;N2wwJ}KA95G`1J1b@y#N3J diff --git a/textAdventure.c b/textAdventure.c index 04afbdc..4248abc 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -11,6 +11,7 @@ struct threadVars{ /* struct because I can only pass one argument to the threads unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ FILE** finptr; /* double pointer because inputThread might change the file */ int* paused; + unsigned int* timeDelay; }; /* Prevents the program from continuing for a certain amount of seconds */ @@ -31,8 +32,11 @@ int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ int stringIndex = 0; fgets(input, MAX_MESSAGE_LENGTH, fin); if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ - printf("%s", input + stringIndex); + printf("%d: %s", *gameTime, input + stringIndex); delay(*timeDelay); + }else if(sscanf(input, "s%u] ", timeDelay)){ + /* if it's an ongoing event, it should not have a delay */ + *timeDelay = 0; }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ return 0; } @@ -46,10 +50,10 @@ void* outputThread(void* arg){ /* store this as a pointer because it might get changed by the other thread */ int* paused = vars->paused; /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ - int timeDelay = 0; + int* timeDelay = vars->timeDelay; /* if paused is true, then it won't even bother checking the other side of the || so readNextLine will never be executed. */ - while(*paused || readNextLine(*finptr, gameTime, &timeDelay)); + while(*paused || readNextLine(*finptr, gameTime, timeDelay)); /* if the code reaches this point, it's time to exit! */ printf("The end! Feel free to play again using a different camera! Exiting...\n"); exit(0); @@ -62,35 +66,40 @@ previousMessageTime */ /* gameTime: the time, in seconds, since the program started (not including pause time) */ /* finptr: a pointer to the file stream in question */ /* returns 1 if the file exists, or 0 if it does not */ -int switchCamera(char* name, unsigned int gameTime, FILE** finptr){ +int switchCamera(char* name, unsigned int gameTime, FILE** finptr, int* timeDelay){ char path[50]; sprintf(path, "./Cameras/%s.txt", name); FILE* open = fopen(path, "r"); if(open == NULL) return 0; fclose(*finptr); /* close the currently open file to prevent memory leaks */ *finptr = open; - int skipTime = 0; - + unsigned int skipTime = 0; + *timeDelay = 0; /* reset the timeDelay so the time doesn't advance when it shouldn't */ char nextLine[MAX_MESSAGE_LENGTH]; /* loops until the stream is right before the first message that should be printed at or after the gameTime */ while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ int lineDelay, stringIndex; char eventType; - if(sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex) == 3){ + + //printf("%d\n", sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex)); + if(sscanf(nextLine, "%c%d] %n", &eventType, timeDelay, &stringIndex) >= 2){ switch(eventType){ /* if it starts with a d, it is an instant event, and because it happened in the past, the message shouldn't print because the player didn't witness it */ case 'd': - skipTime += lineDelay; + skipTime += *timeDelay; + break; /* if it starts with a d, it is an ongoing event, and although the player didn't witness it starting, they still see it before it's over, so it should print */ case 's': - if(skipTime + lineDelay >= gameTime) + if(skipTime + *timeDelay >= gameTime) printf("%s", nextLine + stringIndex); + *timeDelay = 0; break; } }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ + printf("%u %u %s\n", gameTime, skipTime, nextLine); printf("Camera has already ended. Quitting\n"); exit(0); } @@ -103,7 +112,7 @@ int switchCamera(char* name, unsigned int gameTime, FILE** finptr){ /* gameTime: the time, in seconds, since the program started (not including pause time) */ /* finptr: a pointer to the event stream that might be changed by a command */ /* paused: boolean value representing whether or not the output is paused */ -void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused){ +void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused, unsigned int* timeDelay){ /* use strcmp here because the string should consist solely of '\n' */ if(strcmp(command, "\n") == 0){ *paused = !*paused; @@ -116,7 +125,7 @@ void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, i char arg[25]; if(sscanf(command, "camera %s", arg)){ /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ - if(switchCamera(arg, *gameTime, finptr)) return; + if(switchCamera(arg, *gameTime, finptr, timeDelay)) return; /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras the list is hardcoded because there is no platform independent way to list files as far as I know */ printf("The cameras are: start\n"); @@ -134,18 +143,20 @@ void* inputThread(void* arg){ unsigned int* gameTime = vars->gameTime; FILE** finptr = vars->finptr; int* paused = vars->paused; + unsigned int* timeDelay = vars->timeDelay; int inputLength = 100; char input[inputLength]; while(1) - handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused); + handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused, timeDelay); } int main(){ int gameTime = 0; FILE* fin = fopen("./Cameras/start.txt", "r"); int paused = 0; - struct threadVars vars = {&gameTime, &fin, &paused}; + int timeDelay = 0; + struct threadVars vars = {&gameTime, &fin, &paused, &timeDelay}; /* declare threads */ pthread_t outpThread; pthread_t inpThread; From 270eb66a85bfe6c254e1a982ff3e28b1bda3be8c Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Jul 2016 11:30:10 -0400 Subject: [PATCH 10/18] Wrote tutorial/sample game --- Cameras/otherCamera.txt | 17 +++++++++++++++++ Cameras/start.txt | 10 ++++++++++ README.md | 2 -- textAdventure | Bin 13640 -> 13640 bytes textAdventure.c | 4 ++-- 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 Cameras/otherCamera.txt diff --git a/Cameras/otherCamera.txt b/Cameras/otherCamera.txt new file mode 100644 index 0000000..c13bb3a --- /dev/null +++ b/Cameras/otherCamera.txt @@ -0,0 +1,17 @@ +s27] There is a tired looking man at his desk +d5] There is a man sleeping at his desk +d3] He wakes up +d3] He looks around +d5] He shrugs and twiddles his thumbs +d3] He scratches his head +d3] He closes his eyes +d5] He starts to fall asleep again +d1] He wakes up with a start +d3] Man: Oh! Hello! Welcome to the other camera! +d1] Man: Erm, that's... +d1] Man: Uh... +d3] Man: My teleprompter doesn't say anything else +d3] The man looks somewhere out of the camera's field of view +d3] The man appears to be mouthing words at someone +d3] Man: Erm... TECHNICAL DIFFICULTIES +_end diff --git a/Cameras/start.txt b/Cameras/start.txt index dbfc8a9..cc930b4 100644 --- a/Cameras/start.txt +++ b/Cameras/start.txt @@ -4,4 +4,14 @@ d3] He clears his throat. d3] He tightens his tie. d2] He clears his throat again. d3] Man: Welcome to the text adventure! +d5] Man: To pause the game, press enter. Try it! +d3] Man: This game is all about cameras. +d5] Man: To change cameras, pause the game and type "camera otherCamera" +d4] Man: Go ahead, I'll wait +d4] Oh, Hell. The teleprompter's broken +d3] The man runs to the edge of the camera's view +d2] The man waves, trying to get someone's attention +d3] The man makes difficult-to-interpret hand gestures at the person +d3] The man glares +d3] The man stage whispers: You're fired _end diff --git a/README.md b/README.md index db65291..80b6989 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,5 @@ Witnessed events are events that only print if the player is watching the camera Ongoing events are events that only print if the player switches to the camera that the event is on after the event starts and before it stops. The syntax for an ongoing event is `"s] "` where `` is the time, in seconds, between the event starting and the event ending, and `` is the message to be sent ### Automatic exit To automatically quit the program, put "_end" or "_exit" at the end of the file. -# Differences from the proposal -I originally planned to make a game, rather than just a system for the game to run on. The system was significantly more difficult than I expected, and I didn't have any time left to write the story. # How to compile it to compile it, use `gcc textAdventure.c -o textAdventure -lpthread` diff --git a/textAdventure b/textAdventure index d621d2d82c397ae619f9ba022c0bf7b729c28e8d..ca4b24fe0b72d7fd8aafa2f5df5a8a0d202c747c 100755 GIT binary patch delta 1112 zcmZuxYe8ME$xED}$sYR?eoBV{Vc~ltHV;u-ls< zArzHGV4yAJE65pz&VGc2kr9PKKPCnVSiNNakcKpVq%i%@LMVte^X`GB7S!?!q? zs5cbpymLTOSW)5VvnzwDfqMjNM9~wl^&HklRj5t4Ms*kSU%j06)&Db41n;AlXpUk*X-AeH*!CKVCw1fU+kjzKtbWhe*lZ8C-hIjQf~z=>;VFtNG<&+H`DdpXcj`Ysv?4h8T_+ z9d&K(biQC7^1u{R9)6Pvm%{y+;>sSmp7gREGjzoiJ8v}CQtIWMFCVol{{a&j=ql~| z%kGg9-oJ?sDIu^@GT0KE6i+ZS__QWRsX4`Z5T!;Bme@-PHe%B@R&ivnslFPArdm5g zAu+C6-pFb3Z;NE>({bIIq{3|C_8SkG8jLp1*kD@2+3dy!dlqN0n@tTR0f1N=Sq0c0 zzt3Qv6h(GFP2WVZ8Dsr-Q5?b8fzgj~1}!B~LXP9P6=A%Gx3UZ4CwwhU7`^!B+As?E zeg%x_Fi({kGBF7SsvOz{MwO191E)%p(t!;skwA(SF{eXHqQgTgXw>`&vItXbw;y0o zrJ?I#49Be?Q)_57WZ;+%8`YW+|4*n>mr>5$t=31l=@LsA6~LOBh#6<<6s1FOa@l!I z#cIoGJ5*{9&`S3c?RiR9f4p5^DEGVY?|g9eSp!2LPE2qDM`6aGN~+R;&@w@ z2g{)RHE2adu_W!srhPeo6!uT)kJ6t-K?#|&thaObI_pnkyU)4jJm)#*J@>u~HHVt7 zO(eb4lIZ8<^{HU0FHPF`(kxNK2lwcE&G6jzgwWGjfmHPDzm+lLJ-KDLz~3J?lt{b% z)k$~hky63+`L`(Y{k*5|D>LYGUT{sIB@p-PAW>V$5Yr3q{)Iuo6_O%j;aN03o#cf+ z=HWdqmK<1#blyECWi-Ja`MRtW$rbKp`L2<+%ota_6gUf4pKw4uy&X+B)20_9Is5)Kc~axUJYk&%wB&j$Q>*N<(J{Mx+Mb{D`)E8u??< znOytS9IGB{YuC^Jw3R0XoW;Dy!=6p(^Rm@-8CM+4`Q<8&SS8ra`pschVzl88pjK|A zRZyxl&^b7&+(zeNK$*L(aX}P6K0*pFRE7eRn1$mC8(5>R5hoX%W;*4JB*aMBc%Y25 zxB$uATIvBamt9bV&hShGk02+iv~P(tfT>I=S(;lXZi6+9I|vuKbQ*x0+!OUKm7dj~ z7WO`Hzh%;9s8dxX0^_ZQ`>L|efZRd?>_J#`(>!W=4o>i%$`J2<_sq-v6XaM>s2o{l zKa?DyWyc-KF~p=O+R?M&g}ssEe4)Z<#v;xY;mCJU9DmWk=_&{*I}G;Jp7`S>`d+mL zGStW94q|N6v#%o=y3~(XA2?ytAG5aD>{f@~YPXf>9Zsv=Nm|>QoKT-uU)}yq6xoow z=S1-$;ssQnL>xqnAg1HsGAJQ85Q`CC;rwe57xB#75vTE@^&^Jx&JH0KgI2RKj?6*1 zW-}duR*i`cz%7l=Fo*@LNFZfORae}Ol*ITWRIyS<)}ZS${=UPMMn@090E_%2d!DFaO2LJr&#UM`W|$p8msUfsWmoI ztAEtkLun~go6gV{7&qn8Zdfn{X}~{h{vxAK;a+}j(%-* Date: Fri, 15 Jul 2016 14:15:57 -0400 Subject: [PATCH 11/18] Updated README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 80b6989..659b28d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +#Important note!!11!1 +I'm working on a much cleaner, more organized version of this project that I'll upload on sunday at the latest #How to play the game The game consists of a series of messages that print out at specific times. The player interacts with the game using commands. Although not required, before writing a command, press enter to pause the messages, then write the command, then press enter again to unpause them. The commands are as follows. ### Pausing the game From ed8b543d6f94b4c2277152fe0de209f8542442c5 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 17 Jul 2016 14:55:10 -0400 Subject: [PATCH 12/18] started rewrite --- {Cameras => OldVersion/Cameras}/delayTest.txt | 0 .../Cameras}/otherCamera.txt | 0 {Cameras => OldVersion/Cameras}/start.txt | 0 {Cameras => OldVersion/Cameras}/syntax.md | 0 {Cameras => OldVersion/Cameras}/test1.txt | 0 {Cameras => OldVersion/Cameras}/test2.txt | 0 README.md => OldVersion/README.md | 2 - README_OLD.md => OldVersion/README_OLD.md | 0 textAdventure => OldVersion/textAdventure | Bin OldVersion/textAdventure.c | 172 +++++++++ OldVersion/thread.c | 30 ++ textAdventure.c | 331 ++++++++++-------- 12 files changed, 382 insertions(+), 153 deletions(-) rename {Cameras => OldVersion/Cameras}/delayTest.txt (100%) rename {Cameras => OldVersion/Cameras}/otherCamera.txt (100%) rename {Cameras => OldVersion/Cameras}/start.txt (100%) rename {Cameras => OldVersion/Cameras}/syntax.md (100%) rename {Cameras => OldVersion/Cameras}/test1.txt (100%) rename {Cameras => OldVersion/Cameras}/test2.txt (100%) rename README.md => OldVersion/README.md (92%) rename README_OLD.md => OldVersion/README_OLD.md (100%) rename textAdventure => OldVersion/textAdventure (100%) create mode 100644 OldVersion/textAdventure.c create mode 100644 OldVersion/thread.c diff --git a/Cameras/delayTest.txt b/OldVersion/Cameras/delayTest.txt similarity index 100% rename from Cameras/delayTest.txt rename to OldVersion/Cameras/delayTest.txt diff --git a/Cameras/otherCamera.txt b/OldVersion/Cameras/otherCamera.txt similarity index 100% rename from Cameras/otherCamera.txt rename to OldVersion/Cameras/otherCamera.txt diff --git a/Cameras/start.txt b/OldVersion/Cameras/start.txt similarity index 100% rename from Cameras/start.txt rename to OldVersion/Cameras/start.txt diff --git a/Cameras/syntax.md b/OldVersion/Cameras/syntax.md similarity index 100% rename from Cameras/syntax.md rename to OldVersion/Cameras/syntax.md diff --git a/Cameras/test1.txt b/OldVersion/Cameras/test1.txt similarity index 100% rename from Cameras/test1.txt rename to OldVersion/Cameras/test1.txt diff --git a/Cameras/test2.txt b/OldVersion/Cameras/test2.txt similarity index 100% rename from Cameras/test2.txt rename to OldVersion/Cameras/test2.txt diff --git a/README.md b/OldVersion/README.md similarity index 92% rename from README.md rename to OldVersion/README.md index 659b28d..80b6989 100644 --- a/README.md +++ b/OldVersion/README.md @@ -1,5 +1,3 @@ -#Important note!!11!1 -I'm working on a much cleaner, more organized version of this project that I'll upload on sunday at the latest #How to play the game The game consists of a series of messages that print out at specific times. The player interacts with the game using commands. Although not required, before writing a command, press enter to pause the messages, then write the command, then press enter again to unpause them. The commands are as follows. ### Pausing the game diff --git a/README_OLD.md b/OldVersion/README_OLD.md similarity index 100% rename from README_OLD.md rename to OldVersion/README_OLD.md diff --git a/textAdventure b/OldVersion/textAdventure similarity index 100% rename from textAdventure rename to OldVersion/textAdventure diff --git a/OldVersion/textAdventure.c b/OldVersion/textAdventure.c new file mode 100644 index 0000000..5b2168c --- /dev/null +++ b/OldVersion/textAdventure.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +/* Have to use #define because using a const throws an error about variables +being used in array initializers.*/ +#define MAX_MESSAGE_LENGTH 256 + +struct threadVars{ /* struct because I can only pass one argument to the threads */ + unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ + FILE** finptr; /* double pointer because inputThread might change the file */ + int* paused; + unsigned int* timeDelay; +}; + +/* Prevents the program from continuing for a certain amount of seconds */ +/* seconds: the amount of seconds to wait */ +void delay(unsigned int seconds){ + unsigned int start = time(0); + while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; +} + +/* Reads the next line in the stream of events */ +/* fin: the stream of events to read from */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* timeDelay: the delay, in seconds, between the previous event and the current event */ +/* returns 1 if the game should continue, or 0 if the game is over */ +int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ + *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ + char input[MAX_MESSAGE_LENGTH]; + int stringIndex = 0; + fgets(input, MAX_MESSAGE_LENGTH, fin); + if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ + printf("%s", input + stringIndex); + delay(*timeDelay); + }else if(sscanf(input, "s%u] ", timeDelay)){ + /* if it's an ongoing event, it should not have a delay */ + *timeDelay = 0; + }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ + return 0; + } + return 1; +} + +void* outputThread(void* arg){ + struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + /* store this as a pointer because it might get changed by the other thread */ + int* paused = vars->paused; + /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ + int* timeDelay = vars->timeDelay; + /* if paused is true, then it won't even bother checking the other side of + the || so readNextLine will never be executed. */ + while(*paused || readNextLine(*finptr, gameTime, timeDelay)); + /* if the code reaches this point, it's time to exit! */ + printf("The end! Feel free to play again using a different camera! Exiting...\n"); + exit(0); +} + +/* If there exists a file named "Cameras/.txt", will switch fin to that, +move the stream to the first message that comes chronologically after +previousMessageTime */ +/* name: the name of the camera in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the file stream in question */ +/* returns 1 if the file exists, or 0 if it does not */ +int switchCamera(char* name, unsigned int gameTime, FILE** finptr, int* timeDelay){ + char path[50]; + sprintf(path, "./Cameras/%s.txt", name); + FILE* open = fopen(path, "r"); + if(open == NULL) return 0; + fclose(*finptr); /* close the currently open file to prevent memory leaks */ + *finptr = open; + unsigned int skipTime = 0; + *timeDelay = 0; /* reset the timeDelay so the time doesn't advance when it shouldn't */ + char nextLine[MAX_MESSAGE_LENGTH]; + /* loops until the stream is right before the first message that should be printed at or after the gameTime */ + while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ + int lineDelay, stringIndex; + char eventType; + + //printf("%d\n", sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex)); + if(sscanf(nextLine, "%c%d] %n", &eventType, timeDelay, &stringIndex) >= 2){ + switch(eventType){ + /* if it starts with a d, it is an instant event, and because it happened in the past, + the message shouldn't print because the player didn't witness it */ + case 'd': + skipTime += *timeDelay; + + break; + /* if it starts with a d, it is an ongoing event, and although the player didn't + witness it starting, they still see it before it's over, so it should print */ + case 's': + if(skipTime + *timeDelay >= gameTime) + printf("%s", nextLine + stringIndex); + *timeDelay = 0; + break; + } + }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ + printf("%u %u %s\n", gameTime, skipTime, nextLine); + printf("Camera has already ended. Quitting\n"); + exit(0); + } + } + return 1; +} + +/* identifies the command that the player has input and executes it.*/ +/* command: the command in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the event stream that might be changed by a command */ +/* paused: boolean value representing whether or not the output is paused */ +void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused, unsigned int* timeDelay){ + /* use strcmp here because the string should consist solely of '\n' */ + if(strcmp(command, "\n") == 0){ + *paused = !*paused; + if(*paused) + printf("Game is paused. To unpause, press enter\n"); + }else if(strstr(command, "help") != NULL){ + printf("To switch cameras, type \"camera\"\n\ + To quit, type \"quit\"\n"); + }else if(strstr(command, "camera") != NULL){ + char arg[25]; + if(sscanf(command, "camera %s", arg)){ + /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ + if(switchCamera(arg, *gameTime, finptr, timeDelay)) return; + /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras + the list is hardcoded because there is no platform independent way to list files as far as I know */ + printf("The cameras are: start, otherCamera\n"); + } + }else if(strstr(command, "quit") != NULL){ + exit(0); + }else{ + printf("Command not recognised. Type \"help\" for a list of commands\n"); + } +} + +/* Waits for player input and processes it */ +void* inputThread(void* arg){ + struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + int* paused = vars->paused; + unsigned int* timeDelay = vars->timeDelay; + + int inputLength = 100; + char input[inputLength]; + while(1) + handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused, timeDelay); +} + +int main(){ + int gameTime = 0; + FILE* fin = fopen("./Cameras/start.txt", "r"); + int paused = 0; + int timeDelay = 0; + struct threadVars vars = {&gameTime, &fin, &paused, &timeDelay}; + /* declare threads */ + pthread_t outpThread; + pthread_t inpThread; + /* create threads */ + pthread_create(&outpThread, NULL, outputThread, &vars); + pthread_create(&inpThread, NULL, inputThread, &vars); + /* link the threads to their return values(?) */ + pthread_join(outpThread, NULL); + pthread_join(inpThread, NULL); + fclose(fin); + return 0; +} +//FILE* fin = fopen("./Cameras/exampleCam.txt", "r"); diff --git a/OldVersion/thread.c b/OldVersion/thread.c new file mode 100644 index 0000000..2c876b8 --- /dev/null +++ b/OldVersion/thread.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +int keepSayingHi = 1; +void* thread1(){ + int start = time(0); + while(keepSayingHi){ + if(time(0) - start >= 1){ + printf("hi\n"); + start = time(0); + } + } +} + +void* thread2(){ + int num; + scanf("Exit %d", &num); + printf("Exiting\n"); + keepSayingHi = 0; +} + +int main(){ + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, thread1, NULL); + pthread_create(&tid2, NULL, thread2, NULL); + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); +} diff --git a/textAdventure.c b/textAdventure.c index 5b2168c..a66c222 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -1,172 +1,201 @@ #include -#include #include -#include #include -/* Have to use #define because using a const throws an error about variables -being used in array initializers.*/ -#define MAX_MESSAGE_LENGTH 256 - -struct threadVars{ /* struct because I can only pass one argument to the threads */ - unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ - FILE** finptr; /* double pointer because inputThread might change the file */ - int* paused; - unsigned int* timeDelay; -}; - -/* Prevents the program from continuing for a certain amount of seconds */ -/* seconds: the amount of seconds to wait */ -void delay(unsigned int seconds){ - unsigned int start = time(0); - while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; -} +#include +#include -/* Reads the next line in the stream of events */ -/* fin: the stream of events to read from */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* timeDelay: the delay, in seconds, between the previous event and the current event */ -/* returns 1 if the game should continue, or 0 if the game is over */ -int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ - *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ - char input[MAX_MESSAGE_LENGTH]; - int stringIndex = 0; - fgets(input, MAX_MESSAGE_LENGTH, fin); - if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ - printf("%s", input + stringIndex); - delay(*timeDelay); - }else if(sscanf(input, "s%u] ", timeDelay)){ - /* if it's an ongoing event, it should not have a delay */ - *timeDelay = 0; - }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ - return 0; +#define MAX_LINE_LENGTH 1024 /* Making it stupidly long just in case */ + +#define INSTANT_EVENT_MARKER "_i " +#define ONGOING_EVENT_ABSOLUTE_MARKER "_ot " +#define ONGOING_EVENT_RELATIVE_MARKER "_ow " +#define WAIT_ABSOLUTE_MARKER "_wa " +#define WAIT_RELATIVE_MARKER "_wr " +#define COMMENT_MARKER "//" +#define QUIT_MARKER "_q" + +typedef enum InstructionType { + INSTANT_EVENT, + ONGOING_EVENT_ABSOLUTE, + ONGOING_EVENT_RELATIVE, + WAIT_ABSOLUTE, + WAIT_RELATIVE, + COMMENT, + QUIT, + UNDEFINED +}InstructionType; + +/* checks if the line starts with the marker */ +/* line: the line in question */ +/* marker: the marker that the line will be checked for */ +/* args: The string to store the rest of the line, after the marker */ +/* returns 1 if the line contains the marker, otherwise 0 */ +int checkInstructionMarker(char* line, const char* marker, char** args){ + if(memcmp(line, marker, strlen(marker)) == 0){ + *args = line + strlen(marker); + return 1; } - return 1; + return 0; +} + +/* Parses the next instruction in the next line of stream */ +/* camera: the stream to read the line from */ +/* args: the string to copy the intstruction's arguments to, if there are any */ +/* returns: the InstructionType of the next instruction */ +InstructionType getNextInstruction(FILE* camera, char** args){ + /* currently, there is no need for this function, but in theory, there could be a command called + "_a" and a command called "_ab" and this function could serve to make sure that the "_ab" gets checked + before the "_a" to prevent false positives */ + char line[MAX_LINE_LENGTH]; + fgets(line, MAX_LINE_LENGTH, camera); + if(checkInstructionMarker(line, INSTANT_EVENT_MARKER, args)) return INSTANT_EVENT; + if(checkInstructionMarker(line, ONGOING_EVENT_ABSOLUTE_MARKER, args)) return ONGOING_EVENT_ABSOLUTE; + if(checkInstructionMarker(line, ONGOING_EVENT_RELATIVE_MARKER, args)) return ONGOING_EVENT_RELATIVE; + if(checkInstructionMarker(line, WAIT_ABSOLUTE_MARKER, args)) return WAIT_ABSOLUTE; + if(checkInstructionMarker(line, WAIT_RELATIVE_MARKER, args)) return WAIT_RELATIVE; + if(checkInstructionMarker(line, COMMENT_MARKER, args)) return COMMENT; + if(checkInstructionMarker(line, QUIT_MARKER, args)) return QUIT; + return UNDEFINED; } -void* outputThread(void* arg){ - struct threadVars* vars = arg; - unsigned int* gameTime = vars->gameTime; - FILE** finptr = vars->finptr; - /* store this as a pointer because it might get changed by the other thread */ - int* paused = vars->paused; - /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ - int* timeDelay = vars->timeDelay; - /* if paused is true, then it won't even bother checking the other side of - the || so readNextLine will never be executed. */ - while(*paused || readNextLine(*finptr, gameTime, timeDelay)); - /* if the code reaches this point, it's time to exit! */ - printf("The end! Feel free to play again using a different camera! Exiting...\n"); +/* parses a string formatted like a clock (IE %d:%d) */ +/* timeToParse: The string to parse */ +/* stLen: a pointer that will be set to the character length of the time string */ +/* returns: the time that the string represents */ +unsigned long int parseTimeString(char* timeToParse, int* stLen){ + unsigned int hours = 0, minutes = 0, seconds = 0; + if(sscanf(timeToParse, "%u:%u:%u%n", &hours, &minutes, &seconds, stLen) + || sscanf(timeToParse, "%u:%u%n", &minutes, &seconds, stLen) + || scanf(timeToParse, "%u%n", &seconds, stLen)){ + return (((hours * 60) + minutes) * 60) + seconds; + } + printf("Error: Invalid time string. Exiting\n"); exit(0); } +/* Exits the program if verify is less than current */ +/* currentTime: the time to test against */ +/* verify: the time to verify */ +/* returns: nothing if verify is less than current, otherwise returns verify */ +unsigned long int verifyTime(unsigned long int currentTime, unsigned long int verify){ + if(verify < currentTime){ + printf("Error: time (%lu seconds) is less than the current time (%lu seconds)\n", verify, currentTime); + exit(0); + } + return verify; +} + +/* Advances the camera till the time */ +/* camera: the camera in question */ +/* currentTime: the time that the camera is currently on */ +/* to: the time that the camera should fast forward to */ +/* returns 1 if the game should continue, or 0 if it should end */ +int fastForward(FILE* camera, unsigned long int currentTime, unsigned long int to){ + /* Note: currentTime is not a pointer. It will not be changed outside the scope of this function */ + verifyTime(currentTime, to); + + while(currentTime < to){ + char* args; + int argOffset; + InstructionType instType = getNextInstruction(camera, &args); -/* If there exists a file named "Cameras/.txt", will switch fin to that, -move the stream to the first message that comes chronologically after -previousMessageTime */ -/* name: the name of the camera in question */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* finptr: a pointer to the file stream in question */ -/* returns 1 if the file exists, or 0 if it does not */ -int switchCamera(char* name, unsigned int gameTime, FILE** finptr, int* timeDelay){ - char path[50]; - sprintf(path, "./Cameras/%s.txt", name); - FILE* open = fopen(path, "r"); - if(open == NULL) return 0; - fclose(*finptr); /* close the currently open file to prevent memory leaks */ - *finptr = open; - unsigned int skipTime = 0; - *timeDelay = 0; /* reset the timeDelay so the time doesn't advance when it shouldn't */ - char nextLine[MAX_MESSAGE_LENGTH]; - /* loops until the stream is right before the first message that should be printed at or after the gameTime */ - while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ - int lineDelay, stringIndex; - char eventType; - - //printf("%d\n", sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex)); - if(sscanf(nextLine, "%c%d] %n", &eventType, timeDelay, &stringIndex) >= 2){ - switch(eventType){ - /* if it starts with a d, it is an instant event, and because it happened in the past, - the message shouldn't print because the player didn't witness it */ - case 'd': - skipTime += *timeDelay; - - break; - /* if it starts with a d, it is an ongoing event, and although the player didn't - witness it starting, they still see it before it's over, so it should print */ - case 's': - if(skipTime + *timeDelay >= gameTime) - printf("%s", nextLine + stringIndex); - *timeDelay = 0; - break; - } - }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ - printf("%u %u %s\n", gameTime, skipTime, nextLine); - printf("Camera has already ended. Quitting\n"); - exit(0); + switch(instType){ + case WAIT_ABSOLUTE: + currentTime = verifyTime(currentTime, parseTimeString(args, NULL)); + break; + case WAIT_RELATIVE: + currentTime += parseTimeString(args, NULL); + break; + case ONGOING_EVENT_ABSOLUTE: + if(verifyTime(currentTime, parseTimeString(args, &argOffset)) > to) + printf("%s", args + argOffset); + break; + case ONGOING_EVENT_RELATIVE: + if(currentTime + parseTimeString(args, &argOffset) > to) + printf("%s", args + argOffset); + break; + case QUIT: + case UNDEFINED: + return 0; } } - return 1; } -/* identifies the command that the player has input and executes it.*/ -/* command: the command in question */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* finptr: a pointer to the event stream that might be changed by a command */ -/* paused: boolean value representing whether or not the output is paused */ -void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused, unsigned int* timeDelay){ - /* use strcmp here because the string should consist solely of '\n' */ - if(strcmp(command, "\n") == 0){ - *paused = !*paused; - if(*paused) - printf("Game is paused. To unpause, press enter\n"); - }else if(strstr(command, "help") != NULL){ - printf("To switch cameras, type \"camera\"\n\ - To quit, type \"quit\"\n"); - }else if(strstr(command, "camera") != NULL){ - char arg[25]; - if(sscanf(command, "camera %s", arg)){ - /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ - if(switchCamera(arg, *gameTime, finptr, timeDelay)) return; - /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras - the list is hardcoded because there is no platform independent way to list files as far as I know */ - printf("The cameras are: start, otherCamera\n"); - } - }else if(strstr(command, "quit") != NULL){ - exit(0); - }else{ - printf("Command not recognised. Type \"help\" for a list of commands\n"); +/* changes the camera to point to a txt file in the /Cameras directory, if such a file exists */ +/* name: the name of the file in question. The full path to the file will be "./Cameras/.txt" */ +/* camera: the camera to change */ +/* returns: 1 if the camera has been changed, or 0 if it has not been changed */ +int setCamera(char* name, FILE** camera){ + char path[100]; /* stupidly long just in case */ +} + +/* Given a user-input string, will check if it is a valid command, and if so, execute it */ +/* str: The string to check */ +/* currentTime: the current game time. May be changed if the command requires it */ +/* camera: the current event stream. May be changed if the command requires it */ +/* paused: a boolean representing whether or not the output is paused. May be changed if the command requires it */ +int handleCommand(char* str, unsigned long int* currentTime, FILE** camera, int* paused){ + /* remember to pause before changing the camera */ + +} + +void delay(unsigned long int* currentTime, int* paused, unsigned long int seconds){ + /* do it with a for loop so that I can increment currentTime properly */ + for(int i = 0; i < seconds; i++){ + unsigned long int start = time(0); + while((time(0) - start < 1)) if(*paused) return; /* Will loop for 1 second */ + *currentTime++; /* increase the time by 1 */ } } -/* Waits for player input and processes it */ -void* inputThread(void* arg){ - struct threadVars* vars = arg; - unsigned int* gameTime = vars->gameTime; - FILE** finptr = vars->finptr; - int* paused = vars->paused; - unsigned int* timeDelay = vars->timeDelay; - - int inputLength = 100; - char input[inputLength]; - while(1) - handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused, timeDelay); +int readNextLine(int* currentTime, FILE** camera, int* paused){ + char* nextLineArgs; + InstructionType instType = getNextInstruction(*camera, &nextLineArgs); + switch(instType){ + case INSTANT_EVENT: + printf("%s", nextLineArgs); + break; + case WAIT_ABSOLUTE: + delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(nextLineArgs, NULL)) - *currentTime); + break; + case WAIT_RELATIVE: + delay(currentTime, paused, parseTimeString(nextLineArgs, NULL)); + break; + case QUIT: + case UNDEFINED: + return 0; + } + return 1; +} + +typedef struct GameData{ + unsigned long int* currentTime; + FILE** camera; + int* paused; /* boolean */ +}GameData; + +void* outputThread(void* args){ + GameData* gd = args; + unsigned long int* currentTime = args->currentTime; + FILE** camera = args->camera; + int* paused = args->paused; + while(*paused || readNextLine(currentTime, camera, paused)); } -int main(){ - int gameTime = 0; - FILE* fin = fopen("./Cameras/start.txt", "r"); +void* inputThread(void* args){ + GameData* gd = args; + while() +} + +int main(int argc, char* argv[]){ + unsigned long int gameTime = 0; + FILE* camera; int paused = 0; - int timeDelay = 0; - struct threadVars vars = {&gameTime, &fin, &paused, &timeDelay}; - /* declare threads */ - pthread_t outpThread; - pthread_t inpThread; - /* create threads */ - pthread_create(&outpThread, NULL, outputThread, &vars); - pthread_create(&inpThread, NULL, inputThread, &vars); - /* link the threads to their return values(?) */ - pthread_join(outpThread, NULL); - pthread_join(inpThread, NULL); - fclose(fin); - return 0; + GameData gameData = {&gameTime, &camera, &paused}; + pthread_t inTh; + pthread_t outTh; + pthread_create(&inTh, NULL, inputThread, &gameData); + pthread_create(&outTh, NULL, outputThread, &gameData); + pthread_join(inTh, NULL); + pthread_join(outTh, NULL); + } -//FILE* fin = fopen("./Cameras/exampleCam.txt", "r"); From 85b9d79fa9ee2e2d4990b0560f3d1851e0f5ddac Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 17 Jul 2016 14:55:10 -0400 Subject: [PATCH 13/18] First commit for rewrite. Not functional yet --- {Cameras => OldVersion/Cameras}/delayTest.txt | 0 .../Cameras}/otherCamera.txt | 0 {Cameras => OldVersion/Cameras}/start.txt | 0 {Cameras => OldVersion/Cameras}/syntax.md | 0 {Cameras => OldVersion/Cameras}/test1.txt | 0 {Cameras => OldVersion/Cameras}/test2.txt | 0 README.md => OldVersion/README.md | 2 - README_OLD.md => OldVersion/README_OLD.md | 0 textAdventure => OldVersion/textAdventure | Bin OldVersion/textAdventure.c | 172 +++++++++ OldVersion/thread.c | 30 ++ textAdventure.c | 331 ++++++++++-------- 12 files changed, 382 insertions(+), 153 deletions(-) rename {Cameras => OldVersion/Cameras}/delayTest.txt (100%) rename {Cameras => OldVersion/Cameras}/otherCamera.txt (100%) rename {Cameras => OldVersion/Cameras}/start.txt (100%) rename {Cameras => OldVersion/Cameras}/syntax.md (100%) rename {Cameras => OldVersion/Cameras}/test1.txt (100%) rename {Cameras => OldVersion/Cameras}/test2.txt (100%) rename README.md => OldVersion/README.md (92%) rename README_OLD.md => OldVersion/README_OLD.md (100%) rename textAdventure => OldVersion/textAdventure (100%) create mode 100644 OldVersion/textAdventure.c create mode 100644 OldVersion/thread.c diff --git a/Cameras/delayTest.txt b/OldVersion/Cameras/delayTest.txt similarity index 100% rename from Cameras/delayTest.txt rename to OldVersion/Cameras/delayTest.txt diff --git a/Cameras/otherCamera.txt b/OldVersion/Cameras/otherCamera.txt similarity index 100% rename from Cameras/otherCamera.txt rename to OldVersion/Cameras/otherCamera.txt diff --git a/Cameras/start.txt b/OldVersion/Cameras/start.txt similarity index 100% rename from Cameras/start.txt rename to OldVersion/Cameras/start.txt diff --git a/Cameras/syntax.md b/OldVersion/Cameras/syntax.md similarity index 100% rename from Cameras/syntax.md rename to OldVersion/Cameras/syntax.md diff --git a/Cameras/test1.txt b/OldVersion/Cameras/test1.txt similarity index 100% rename from Cameras/test1.txt rename to OldVersion/Cameras/test1.txt diff --git a/Cameras/test2.txt b/OldVersion/Cameras/test2.txt similarity index 100% rename from Cameras/test2.txt rename to OldVersion/Cameras/test2.txt diff --git a/README.md b/OldVersion/README.md similarity index 92% rename from README.md rename to OldVersion/README.md index 659b28d..80b6989 100644 --- a/README.md +++ b/OldVersion/README.md @@ -1,5 +1,3 @@ -#Important note!!11!1 -I'm working on a much cleaner, more organized version of this project that I'll upload on sunday at the latest #How to play the game The game consists of a series of messages that print out at specific times. The player interacts with the game using commands. Although not required, before writing a command, press enter to pause the messages, then write the command, then press enter again to unpause them. The commands are as follows. ### Pausing the game diff --git a/README_OLD.md b/OldVersion/README_OLD.md similarity index 100% rename from README_OLD.md rename to OldVersion/README_OLD.md diff --git a/textAdventure b/OldVersion/textAdventure similarity index 100% rename from textAdventure rename to OldVersion/textAdventure diff --git a/OldVersion/textAdventure.c b/OldVersion/textAdventure.c new file mode 100644 index 0000000..5b2168c --- /dev/null +++ b/OldVersion/textAdventure.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +/* Have to use #define because using a const throws an error about variables +being used in array initializers.*/ +#define MAX_MESSAGE_LENGTH 256 + +struct threadVars{ /* struct because I can only pass one argument to the threads */ + unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ + FILE** finptr; /* double pointer because inputThread might change the file */ + int* paused; + unsigned int* timeDelay; +}; + +/* Prevents the program from continuing for a certain amount of seconds */ +/* seconds: the amount of seconds to wait */ +void delay(unsigned int seconds){ + unsigned int start = time(0); + while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; +} + +/* Reads the next line in the stream of events */ +/* fin: the stream of events to read from */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* timeDelay: the delay, in seconds, between the previous event and the current event */ +/* returns 1 if the game should continue, or 0 if the game is over */ +int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ + *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ + char input[MAX_MESSAGE_LENGTH]; + int stringIndex = 0; + fgets(input, MAX_MESSAGE_LENGTH, fin); + if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ + printf("%s", input + stringIndex); + delay(*timeDelay); + }else if(sscanf(input, "s%u] ", timeDelay)){ + /* if it's an ongoing event, it should not have a delay */ + *timeDelay = 0; + }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ + return 0; + } + return 1; +} + +void* outputThread(void* arg){ + struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + /* store this as a pointer because it might get changed by the other thread */ + int* paused = vars->paused; + /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ + int* timeDelay = vars->timeDelay; + /* if paused is true, then it won't even bother checking the other side of + the || so readNextLine will never be executed. */ + while(*paused || readNextLine(*finptr, gameTime, timeDelay)); + /* if the code reaches this point, it's time to exit! */ + printf("The end! Feel free to play again using a different camera! Exiting...\n"); + exit(0); +} + +/* If there exists a file named "Cameras/.txt", will switch fin to that, +move the stream to the first message that comes chronologically after +previousMessageTime */ +/* name: the name of the camera in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the file stream in question */ +/* returns 1 if the file exists, or 0 if it does not */ +int switchCamera(char* name, unsigned int gameTime, FILE** finptr, int* timeDelay){ + char path[50]; + sprintf(path, "./Cameras/%s.txt", name); + FILE* open = fopen(path, "r"); + if(open == NULL) return 0; + fclose(*finptr); /* close the currently open file to prevent memory leaks */ + *finptr = open; + unsigned int skipTime = 0; + *timeDelay = 0; /* reset the timeDelay so the time doesn't advance when it shouldn't */ + char nextLine[MAX_MESSAGE_LENGTH]; + /* loops until the stream is right before the first message that should be printed at or after the gameTime */ + while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ + int lineDelay, stringIndex; + char eventType; + + //printf("%d\n", sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex)); + if(sscanf(nextLine, "%c%d] %n", &eventType, timeDelay, &stringIndex) >= 2){ + switch(eventType){ + /* if it starts with a d, it is an instant event, and because it happened in the past, + the message shouldn't print because the player didn't witness it */ + case 'd': + skipTime += *timeDelay; + + break; + /* if it starts with a d, it is an ongoing event, and although the player didn't + witness it starting, they still see it before it's over, so it should print */ + case 's': + if(skipTime + *timeDelay >= gameTime) + printf("%s", nextLine + stringIndex); + *timeDelay = 0; + break; + } + }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ + printf("%u %u %s\n", gameTime, skipTime, nextLine); + printf("Camera has already ended. Quitting\n"); + exit(0); + } + } + return 1; +} + +/* identifies the command that the player has input and executes it.*/ +/* command: the command in question */ +/* gameTime: the time, in seconds, since the program started (not including pause time) */ +/* finptr: a pointer to the event stream that might be changed by a command */ +/* paused: boolean value representing whether or not the output is paused */ +void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused, unsigned int* timeDelay){ + /* use strcmp here because the string should consist solely of '\n' */ + if(strcmp(command, "\n") == 0){ + *paused = !*paused; + if(*paused) + printf("Game is paused. To unpause, press enter\n"); + }else if(strstr(command, "help") != NULL){ + printf("To switch cameras, type \"camera\"\n\ + To quit, type \"quit\"\n"); + }else if(strstr(command, "camera") != NULL){ + char arg[25]; + if(sscanf(command, "camera %s", arg)){ + /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ + if(switchCamera(arg, *gameTime, finptr, timeDelay)) return; + /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras + the list is hardcoded because there is no platform independent way to list files as far as I know */ + printf("The cameras are: start, otherCamera\n"); + } + }else if(strstr(command, "quit") != NULL){ + exit(0); + }else{ + printf("Command not recognised. Type \"help\" for a list of commands\n"); + } +} + +/* Waits for player input and processes it */ +void* inputThread(void* arg){ + struct threadVars* vars = arg; + unsigned int* gameTime = vars->gameTime; + FILE** finptr = vars->finptr; + int* paused = vars->paused; + unsigned int* timeDelay = vars->timeDelay; + + int inputLength = 100; + char input[inputLength]; + while(1) + handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused, timeDelay); +} + +int main(){ + int gameTime = 0; + FILE* fin = fopen("./Cameras/start.txt", "r"); + int paused = 0; + int timeDelay = 0; + struct threadVars vars = {&gameTime, &fin, &paused, &timeDelay}; + /* declare threads */ + pthread_t outpThread; + pthread_t inpThread; + /* create threads */ + pthread_create(&outpThread, NULL, outputThread, &vars); + pthread_create(&inpThread, NULL, inputThread, &vars); + /* link the threads to their return values(?) */ + pthread_join(outpThread, NULL); + pthread_join(inpThread, NULL); + fclose(fin); + return 0; +} +//FILE* fin = fopen("./Cameras/exampleCam.txt", "r"); diff --git a/OldVersion/thread.c b/OldVersion/thread.c new file mode 100644 index 0000000..2c876b8 --- /dev/null +++ b/OldVersion/thread.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +int keepSayingHi = 1; +void* thread1(){ + int start = time(0); + while(keepSayingHi){ + if(time(0) - start >= 1){ + printf("hi\n"); + start = time(0); + } + } +} + +void* thread2(){ + int num; + scanf("Exit %d", &num); + printf("Exiting\n"); + keepSayingHi = 0; +} + +int main(){ + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, thread1, NULL); + pthread_create(&tid2, NULL, thread2, NULL); + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); +} diff --git a/textAdventure.c b/textAdventure.c index 5b2168c..a66c222 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -1,172 +1,201 @@ #include -#include #include -#include #include -/* Have to use #define because using a const throws an error about variables -being used in array initializers.*/ -#define MAX_MESSAGE_LENGTH 256 - -struct threadVars{ /* struct because I can only pass one argument to the threads */ - unsigned int* gameTime; /* Time travelers will (hopefully) never try to run this code before 1970 */ - FILE** finptr; /* double pointer because inputThread might change the file */ - int* paused; - unsigned int* timeDelay; -}; - -/* Prevents the program from continuing for a certain amount of seconds */ -/* seconds: the amount of seconds to wait */ -void delay(unsigned int seconds){ - unsigned int start = time(0); - while(time(0) - start < seconds)/*printf("%ld\b", time(0) - start)*/; -} +#include +#include -/* Reads the next line in the stream of events */ -/* fin: the stream of events to read from */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* timeDelay: the delay, in seconds, between the previous event and the current event */ -/* returns 1 if the game should continue, or 0 if the game is over */ -int readNextLine(FILE* fin, unsigned int* gameTime, unsigned int* timeDelay){ - *gameTime += *timeDelay; /* add the previous message's delay to the game's time */ - char input[MAX_MESSAGE_LENGTH]; - int stringIndex = 0; - fgets(input, MAX_MESSAGE_LENGTH, fin); - if(sscanf(input, "d%u] %n", timeDelay, &stringIndex)){ - printf("%s", input + stringIndex); - delay(*timeDelay); - }else if(sscanf(input, "s%u] ", timeDelay)){ - /* if it's an ongoing event, it should not have a delay */ - *timeDelay = 0; - }else if(strstr(input, "_end") != NULL || strstr(input, "_exit") != NULL){ - return 0; +#define MAX_LINE_LENGTH 1024 /* Making it stupidly long just in case */ + +#define INSTANT_EVENT_MARKER "_i " +#define ONGOING_EVENT_ABSOLUTE_MARKER "_ot " +#define ONGOING_EVENT_RELATIVE_MARKER "_ow " +#define WAIT_ABSOLUTE_MARKER "_wa " +#define WAIT_RELATIVE_MARKER "_wr " +#define COMMENT_MARKER "//" +#define QUIT_MARKER "_q" + +typedef enum InstructionType { + INSTANT_EVENT, + ONGOING_EVENT_ABSOLUTE, + ONGOING_EVENT_RELATIVE, + WAIT_ABSOLUTE, + WAIT_RELATIVE, + COMMENT, + QUIT, + UNDEFINED +}InstructionType; + +/* checks if the line starts with the marker */ +/* line: the line in question */ +/* marker: the marker that the line will be checked for */ +/* args: The string to store the rest of the line, after the marker */ +/* returns 1 if the line contains the marker, otherwise 0 */ +int checkInstructionMarker(char* line, const char* marker, char** args){ + if(memcmp(line, marker, strlen(marker)) == 0){ + *args = line + strlen(marker); + return 1; } - return 1; + return 0; +} + +/* Parses the next instruction in the next line of stream */ +/* camera: the stream to read the line from */ +/* args: the string to copy the intstruction's arguments to, if there are any */ +/* returns: the InstructionType of the next instruction */ +InstructionType getNextInstruction(FILE* camera, char** args){ + /* currently, there is no need for this function, but in theory, there could be a command called + "_a" and a command called "_ab" and this function could serve to make sure that the "_ab" gets checked + before the "_a" to prevent false positives */ + char line[MAX_LINE_LENGTH]; + fgets(line, MAX_LINE_LENGTH, camera); + if(checkInstructionMarker(line, INSTANT_EVENT_MARKER, args)) return INSTANT_EVENT; + if(checkInstructionMarker(line, ONGOING_EVENT_ABSOLUTE_MARKER, args)) return ONGOING_EVENT_ABSOLUTE; + if(checkInstructionMarker(line, ONGOING_EVENT_RELATIVE_MARKER, args)) return ONGOING_EVENT_RELATIVE; + if(checkInstructionMarker(line, WAIT_ABSOLUTE_MARKER, args)) return WAIT_ABSOLUTE; + if(checkInstructionMarker(line, WAIT_RELATIVE_MARKER, args)) return WAIT_RELATIVE; + if(checkInstructionMarker(line, COMMENT_MARKER, args)) return COMMENT; + if(checkInstructionMarker(line, QUIT_MARKER, args)) return QUIT; + return UNDEFINED; } -void* outputThread(void* arg){ - struct threadVars* vars = arg; - unsigned int* gameTime = vars->gameTime; - FILE** finptr = vars->finptr; - /* store this as a pointer because it might get changed by the other thread */ - int* paused = vars->paused; - /* declare timeDelay here because readNextLine needs to access the previous line's timeDelay */ - int* timeDelay = vars->timeDelay; - /* if paused is true, then it won't even bother checking the other side of - the || so readNextLine will never be executed. */ - while(*paused || readNextLine(*finptr, gameTime, timeDelay)); - /* if the code reaches this point, it's time to exit! */ - printf("The end! Feel free to play again using a different camera! Exiting...\n"); +/* parses a string formatted like a clock (IE %d:%d) */ +/* timeToParse: The string to parse */ +/* stLen: a pointer that will be set to the character length of the time string */ +/* returns: the time that the string represents */ +unsigned long int parseTimeString(char* timeToParse, int* stLen){ + unsigned int hours = 0, minutes = 0, seconds = 0; + if(sscanf(timeToParse, "%u:%u:%u%n", &hours, &minutes, &seconds, stLen) + || sscanf(timeToParse, "%u:%u%n", &minutes, &seconds, stLen) + || scanf(timeToParse, "%u%n", &seconds, stLen)){ + return (((hours * 60) + minutes) * 60) + seconds; + } + printf("Error: Invalid time string. Exiting\n"); exit(0); } +/* Exits the program if verify is less than current */ +/* currentTime: the time to test against */ +/* verify: the time to verify */ +/* returns: nothing if verify is less than current, otherwise returns verify */ +unsigned long int verifyTime(unsigned long int currentTime, unsigned long int verify){ + if(verify < currentTime){ + printf("Error: time (%lu seconds) is less than the current time (%lu seconds)\n", verify, currentTime); + exit(0); + } + return verify; +} + +/* Advances the camera till the time */ +/* camera: the camera in question */ +/* currentTime: the time that the camera is currently on */ +/* to: the time that the camera should fast forward to */ +/* returns 1 if the game should continue, or 0 if it should end */ +int fastForward(FILE* camera, unsigned long int currentTime, unsigned long int to){ + /* Note: currentTime is not a pointer. It will not be changed outside the scope of this function */ + verifyTime(currentTime, to); + + while(currentTime < to){ + char* args; + int argOffset; + InstructionType instType = getNextInstruction(camera, &args); -/* If there exists a file named "Cameras/.txt", will switch fin to that, -move the stream to the first message that comes chronologically after -previousMessageTime */ -/* name: the name of the camera in question */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* finptr: a pointer to the file stream in question */ -/* returns 1 if the file exists, or 0 if it does not */ -int switchCamera(char* name, unsigned int gameTime, FILE** finptr, int* timeDelay){ - char path[50]; - sprintf(path, "./Cameras/%s.txt", name); - FILE* open = fopen(path, "r"); - if(open == NULL) return 0; - fclose(*finptr); /* close the currently open file to prevent memory leaks */ - *finptr = open; - unsigned int skipTime = 0; - *timeDelay = 0; /* reset the timeDelay so the time doesn't advance when it shouldn't */ - char nextLine[MAX_MESSAGE_LENGTH]; - /* loops until the stream is right before the first message that should be printed at or after the gameTime */ - while(skipTime < gameTime && fgets(nextLine, MAX_MESSAGE_LENGTH, *finptr)){ - int lineDelay, stringIndex; - char eventType; - - //printf("%d\n", sscanf(nextLine, "%c%d] %n", &eventType, &lineDelay, &stringIndex)); - if(sscanf(nextLine, "%c%d] %n", &eventType, timeDelay, &stringIndex) >= 2){ - switch(eventType){ - /* if it starts with a d, it is an instant event, and because it happened in the past, - the message shouldn't print because the player didn't witness it */ - case 'd': - skipTime += *timeDelay; - - break; - /* if it starts with a d, it is an ongoing event, and although the player didn't - witness it starting, they still see it before it's over, so it should print */ - case 's': - if(skipTime + *timeDelay >= gameTime) - printf("%s", nextLine + stringIndex); - *timeDelay = 0; - break; - } - }else if(strstr(nextLine, "_end") != NULL || strstr(nextLine, "_exit") != NULL){ - printf("%u %u %s\n", gameTime, skipTime, nextLine); - printf("Camera has already ended. Quitting\n"); - exit(0); + switch(instType){ + case WAIT_ABSOLUTE: + currentTime = verifyTime(currentTime, parseTimeString(args, NULL)); + break; + case WAIT_RELATIVE: + currentTime += parseTimeString(args, NULL); + break; + case ONGOING_EVENT_ABSOLUTE: + if(verifyTime(currentTime, parseTimeString(args, &argOffset)) > to) + printf("%s", args + argOffset); + break; + case ONGOING_EVENT_RELATIVE: + if(currentTime + parseTimeString(args, &argOffset) > to) + printf("%s", args + argOffset); + break; + case QUIT: + case UNDEFINED: + return 0; } } - return 1; } -/* identifies the command that the player has input and executes it.*/ -/* command: the command in question */ -/* gameTime: the time, in seconds, since the program started (not including pause time) */ -/* finptr: a pointer to the event stream that might be changed by a command */ -/* paused: boolean value representing whether or not the output is paused */ -void handlePlayerCommand(char* command, unsigned int* gameTime, FILE** finptr, int* paused, unsigned int* timeDelay){ - /* use strcmp here because the string should consist solely of '\n' */ - if(strcmp(command, "\n") == 0){ - *paused = !*paused; - if(*paused) - printf("Game is paused. To unpause, press enter\n"); - }else if(strstr(command, "help") != NULL){ - printf("To switch cameras, type \"camera\"\n\ - To quit, type \"quit\"\n"); - }else if(strstr(command, "camera") != NULL){ - char arg[25]; - if(sscanf(command, "camera %s", arg)){ - /* dereference gameTime because there's no reason to expect that it would change during the execution of switchCamera */ - if(switchCamera(arg, *gameTime, finptr, timeDelay)) return; - /* if no camera is specified or if it is not a valid camera, print out a list of valid cameras - the list is hardcoded because there is no platform independent way to list files as far as I know */ - printf("The cameras are: start, otherCamera\n"); - } - }else if(strstr(command, "quit") != NULL){ - exit(0); - }else{ - printf("Command not recognised. Type \"help\" for a list of commands\n"); +/* changes the camera to point to a txt file in the /Cameras directory, if such a file exists */ +/* name: the name of the file in question. The full path to the file will be "./Cameras/.txt" */ +/* camera: the camera to change */ +/* returns: 1 if the camera has been changed, or 0 if it has not been changed */ +int setCamera(char* name, FILE** camera){ + char path[100]; /* stupidly long just in case */ +} + +/* Given a user-input string, will check if it is a valid command, and if so, execute it */ +/* str: The string to check */ +/* currentTime: the current game time. May be changed if the command requires it */ +/* camera: the current event stream. May be changed if the command requires it */ +/* paused: a boolean representing whether or not the output is paused. May be changed if the command requires it */ +int handleCommand(char* str, unsigned long int* currentTime, FILE** camera, int* paused){ + /* remember to pause before changing the camera */ + +} + +void delay(unsigned long int* currentTime, int* paused, unsigned long int seconds){ + /* do it with a for loop so that I can increment currentTime properly */ + for(int i = 0; i < seconds; i++){ + unsigned long int start = time(0); + while((time(0) - start < 1)) if(*paused) return; /* Will loop for 1 second */ + *currentTime++; /* increase the time by 1 */ } } -/* Waits for player input and processes it */ -void* inputThread(void* arg){ - struct threadVars* vars = arg; - unsigned int* gameTime = vars->gameTime; - FILE** finptr = vars->finptr; - int* paused = vars->paused; - unsigned int* timeDelay = vars->timeDelay; - - int inputLength = 100; - char input[inputLength]; - while(1) - handlePlayerCommand(fgets(input, inputLength, stdin), gameTime, finptr, paused, timeDelay); +int readNextLine(int* currentTime, FILE** camera, int* paused){ + char* nextLineArgs; + InstructionType instType = getNextInstruction(*camera, &nextLineArgs); + switch(instType){ + case INSTANT_EVENT: + printf("%s", nextLineArgs); + break; + case WAIT_ABSOLUTE: + delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(nextLineArgs, NULL)) - *currentTime); + break; + case WAIT_RELATIVE: + delay(currentTime, paused, parseTimeString(nextLineArgs, NULL)); + break; + case QUIT: + case UNDEFINED: + return 0; + } + return 1; +} + +typedef struct GameData{ + unsigned long int* currentTime; + FILE** camera; + int* paused; /* boolean */ +}GameData; + +void* outputThread(void* args){ + GameData* gd = args; + unsigned long int* currentTime = args->currentTime; + FILE** camera = args->camera; + int* paused = args->paused; + while(*paused || readNextLine(currentTime, camera, paused)); } -int main(){ - int gameTime = 0; - FILE* fin = fopen("./Cameras/start.txt", "r"); +void* inputThread(void* args){ + GameData* gd = args; + while() +} + +int main(int argc, char* argv[]){ + unsigned long int gameTime = 0; + FILE* camera; int paused = 0; - int timeDelay = 0; - struct threadVars vars = {&gameTime, &fin, &paused, &timeDelay}; - /* declare threads */ - pthread_t outpThread; - pthread_t inpThread; - /* create threads */ - pthread_create(&outpThread, NULL, outputThread, &vars); - pthread_create(&inpThread, NULL, inputThread, &vars); - /* link the threads to their return values(?) */ - pthread_join(outpThread, NULL); - pthread_join(inpThread, NULL); - fclose(fin); - return 0; + GameData gameData = {&gameTime, &camera, &paused}; + pthread_t inTh; + pthread_t outTh; + pthread_create(&inTh, NULL, inputThread, &gameData); + pthread_create(&outTh, NULL, outputThread, &gameData); + pthread_join(inTh, NULL); + pthread_join(outTh, NULL); + } -//FILE* fin = fopen("./Cameras/exampleCam.txt", "r"); From ef5316ea8da3a5409ccea990f16f0f8dbdb8df86 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 17 Jul 2016 20:36:05 -0400 Subject: [PATCH 14/18] Mostly implemented! Not fully tested, fully organized, or fully documented yet --- Cameras/start.txt | 6 ++ Instructions.c | 59 ++++++++++++ Instructions.h | 23 +++++ adventure | Bin 0 -> 23856 bytes textAdventure.c | 223 ++++++++++++++++++++++++++-------------------- 5 files changed, 214 insertions(+), 97 deletions(-) create mode 100644 Cameras/start.txt create mode 100644 Instructions.c create mode 100644 Instructions.h create mode 100755 adventure diff --git a/Cameras/start.txt b/Cameras/start.txt new file mode 100644 index 0000000..b7671d4 --- /dev/null +++ b/Cameras/start.txt @@ -0,0 +1,6 @@ +i Hello! +wa 4 +i You are now 5 seconds into the game. +wa 5 +i 1 second has passed since the previous message +q diff --git a/Instructions.c b/Instructions.c new file mode 100644 index 0000000..c36211d --- /dev/null +++ b/Instructions.c @@ -0,0 +1,59 @@ +#include "Instructions.h" +#include +#include + +/* Here's a dictionary mapping the types of instruction with the strings that call them */ +/* to differentiate between instructions, it's best to put a space after instructions with arguments and '\n' after instructions without any */ +const InstructionMap instructionCalls[] = { + {INSTANT_EVENT, "i "}, + {INSTANT_EVENT, "instant "}, + {ONGOING_EVENT_ABSOLUTE, "oa "}, + {ONGOING_EVENT_ABSOLUTE, "ongoing_till "}, + {ONGOING_EVENT_RELATIVE, "or "}, + {ONGOING_EVENT_RELATIVE, "ongoing_for "}, + {WAIT_ABSOLUTE, "wa "}, + {WAIT_ABSOLUTE, "wait_till "}, + {WAIT_RELATIVE, "wr "}, + {WAIT_RELATIVE, "wait_for "}, + {COMMENT, "//"}, + {EXIT, "q\n"}, + {EXIT, "quit\n"}, + {EXIT, "exit\n"}, + {EXIT, "end\n"}, + {CHANGE_CAMERA, "c "}, + {CHANGE_CAMERA, "camera "}, + {LIST_CAMERAS, "cameras\n"}, + {PAUSE, "p\n"}, + {PAUSE, "pause\n"}, + {PAUSE, "\n"}, + {PAUSE_SILENT, "ps\n"}, + {PAUSE_SILENT, "pause_silent\n"}, + {HELP, "help\n"}, + {HELP, "h\n"}, + {HELP, "?\n"} +}; + +/* binds the commands that the player can input to their help text */ +const InstructionMap playerInstructionHelp[] = { + {CHANGE_CAMERA, "To change the camera, type \"camera \""}, + {LIST_CAMERAS, "To get a list of cameras, type \"cameras\""}, + {EXIT, "To quit, type \"quit\""}, + {PAUSE, "To pause, press enter"} +}; + +/* Finds the instruction that a string calls */ +/* str: the string that calls an instruction */ +/* Returns: instructionType and the instruction's arguments. If the string doesn't match any instruction, returns UNDEFINED and NULL */ +InstructionMap getInstruction(char* str){ + for(int i = 0; i < sizeof(instructionCalls) / sizeof(InstructionMap); i++){ + if(strncmp(instructionCalls[i].args, str, strlen(instructionCalls[i].args)) == 0){ + return (InstructionMap){instructionCalls[i].type, str + strlen(instructionCalls[i].args)}; + } + } + return (InstructionMap){UNDEFINED, NULL}; +} + +void printHelpText(){ + for(int i = 0; i < sizeof(playerInstructionHelp) / sizeof(InstructionMap); i++) + printf("%s\n", playerInstructionHelp[i].args); +} diff --git a/Instructions.h b/Instructions.h new file mode 100644 index 0000000..3eebf5e --- /dev/null +++ b/Instructions.h @@ -0,0 +1,23 @@ +typedef enum InstructionType{ + UNDEFINED, + INSTANT_EVENT, + ONGOING_EVENT_ABSOLUTE, + ONGOING_EVENT_RELATIVE, + WAIT_ABSOLUTE, + WAIT_RELATIVE, + COMMENT, + EXIT, + CHANGE_CAMERA, + LIST_CAMERAS, + PAUSE, + PAUSE_SILENT, + HELP +}InstructionType; + +typedef struct InstructionMap { /* used to map an instruction to a string */ + InstructionType type; + char* args; +}InstructionMap; + +InstructionMap getInstruction(char* str); +void printHelpText(); diff --git a/adventure b/adventure new file mode 100755 index 0000000000000000000000000000000000000000..2051cfa316d562a18766ce070a96bc593418f249 GIT binary patch literal 23856 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 #include #include +#include "Instructions.h" #define MAX_LINE_LENGTH 1024 /* Making it stupidly long just in case */ +#define MAX_COMMAND_LENGTH 256 /* Making this one stupidly long as well */ -#define INSTANT_EVENT_MARKER "_i " -#define ONGOING_EVENT_ABSOLUTE_MARKER "_ot " -#define ONGOING_EVENT_RELATIVE_MARKER "_ow " -#define WAIT_ABSOLUTE_MARKER "_wa " -#define WAIT_RELATIVE_MARKER "_wr " -#define COMMENT_MARKER "//" -#define QUIT_MARKER "_q" - -typedef enum InstructionType { - INSTANT_EVENT, - ONGOING_EVENT_ABSOLUTE, - ONGOING_EVENT_RELATIVE, - WAIT_ABSOLUTE, - WAIT_RELATIVE, - COMMENT, - QUIT, - UNDEFINED -}InstructionType; - -/* checks if the line starts with the marker */ -/* line: the line in question */ -/* marker: the marker that the line will be checked for */ -/* args: The string to store the rest of the line, after the marker */ -/* returns 1 if the line contains the marker, otherwise 0 */ -int checkInstructionMarker(char* line, const char* marker, char** args){ - if(memcmp(line, marker, strlen(marker)) == 0){ - *args = line + strlen(marker); - return 1; - } - return 0; -} - -/* Parses the next instruction in the next line of stream */ -/* camera: the stream to read the line from */ -/* args: the string to copy the intstruction's arguments to, if there are any */ -/* returns: the InstructionType of the next instruction */ -InstructionType getNextInstruction(FILE* camera, char** args){ - /* currently, there is no need for this function, but in theory, there could be a command called - "_a" and a command called "_ab" and this function could serve to make sure that the "_ab" gets checked - before the "_a" to prevent false positives */ - char line[MAX_LINE_LENGTH]; - fgets(line, MAX_LINE_LENGTH, camera); - if(checkInstructionMarker(line, INSTANT_EVENT_MARKER, args)) return INSTANT_EVENT; - if(checkInstructionMarker(line, ONGOING_EVENT_ABSOLUTE_MARKER, args)) return ONGOING_EVENT_ABSOLUTE; - if(checkInstructionMarker(line, ONGOING_EVENT_RELATIVE_MARKER, args)) return ONGOING_EVENT_RELATIVE; - if(checkInstructionMarker(line, WAIT_ABSOLUTE_MARKER, args)) return WAIT_ABSOLUTE; - if(checkInstructionMarker(line, WAIT_RELATIVE_MARKER, args)) return WAIT_RELATIVE; - if(checkInstructionMarker(line, COMMENT_MARKER, args)) return COMMENT; - if(checkInstructionMarker(line, QUIT_MARKER, args)) return QUIT; - return UNDEFINED; -} +const char* CAMERA_LIST = "start"; /* Hardcoded because there's no platform-independent way to list files */ /* parses a string formatted like a clock (IE %d:%d) */ /* timeToParse: The string to parse */ /* stLen: a pointer that will be set to the character length of the time string */ /* returns: the time that the string represents */ unsigned long int parseTimeString(char* timeToParse, int* stLen){ - unsigned int hours = 0, minutes = 0, seconds = 0; - if(sscanf(timeToParse, "%u:%u:%u%n", &hours, &minutes, &seconds, stLen) - || sscanf(timeToParse, "%u:%u%n", &minutes, &seconds, stLen) - || scanf(timeToParse, "%u%n", &seconds, stLen)){ - return (((hours * 60) + minutes) * 60) + seconds; + unsigned int args[] = {0, 0, 0}; + unsigned long int ret = 0; + for(int i = 0; i < sscanf(timeToParse, "%u:%u:%u%n", args, args + 1, args + 2, stLen); i++){ + ret *= 60; + ret += args[i]; } - printf("Error: Invalid time string. Exiting\n"); - exit(0); + return ret; } + /* Exits the program if verify is less than current */ /* currentTime: the time to test against */ /* verify: the time to verify */ @@ -84,40 +36,65 @@ unsigned long int verifyTime(unsigned long int currentTime, unsigned long int ve return verify; } +/* delays the program for a certain amount of time, or until the program is paused */ +/* currentTime: The current game time. Will be incremented each second */ +/* paused: boolean representing whether or not the output is paused. If the output is paused, +there's no reason to continue delaying, as it is already being delayed elsewhere */ +/* seconds: the time to delay for. */ +void delay(unsigned long int* currentTime, int* paused, unsigned long int seconds){ + /* do it with a for loop so that I can increment currentTime properly */ + //printf("Delay start.\n*currentTime: %lu\nseconds: %lu\n", *currentTime, seconds); + for(int i = 0; i < seconds; i++){ + unsigned long int startSecond = time(0); + while((time(0) - startSecond < 1)){ /* Will loop for 1 second */ + if(*paused){ + *currentTime += seconds - i; + return; + } + } + ++*currentTime; /* increase the time by 1 */ + //printf("CurrentTime increased to %lu\n", *currentTime); + } +} + /* Advances the camera till the time */ /* camera: the camera in question */ -/* currentTime: the time that the camera is currently on */ -/* to: the time that the camera should fast forward to */ +/* fromTime: the time that the camera is currently on */ +/* toTime: the time that the camera should fast forward to. */ /* returns 1 if the game should continue, or 0 if it should end */ -int fastForward(FILE* camera, unsigned long int currentTime, unsigned long int to){ +int fastForward(FILE** camera, unsigned long int fromTime, unsigned long int* toTime){ /* Note: currentTime is not a pointer. It will not be changed outside the scope of this function */ - verifyTime(currentTime, to); + verifyTime(fromTime, *toTime); - while(currentTime < to){ - char* args; + while(fromTime < *toTime){ int argOffset; - InstructionType instType = getNextInstruction(camera, &args); + char line[MAX_LINE_LENGTH]; + fgets(line, MAX_LINE_LENGTH, *camera); + InstructionMap inst = getInstruction(line); - switch(instType){ + switch(inst.type){ case WAIT_ABSOLUTE: - currentTime = verifyTime(currentTime, parseTimeString(args, NULL)); + fromTime = verifyTime(fromTime, parseTimeString(inst.args, NULL)); break; case WAIT_RELATIVE: - currentTime += parseTimeString(args, NULL); + fromTime += parseTimeString(inst.args, NULL); break; case ONGOING_EVENT_ABSOLUTE: - if(verifyTime(currentTime, parseTimeString(args, &argOffset)) > to) - printf("%s", args + argOffset); + if(verifyTime(fromTime, parseTimeString(inst.args, &argOffset)) > *toTime) + printf("%s", inst.args + argOffset); break; case ONGOING_EVENT_RELATIVE: - if(currentTime + parseTimeString(args, &argOffset) > to) - printf("%s", args + argOffset); + if(fromTime + parseTimeString(inst.args, &argOffset) > *toTime) + printf("%s", inst.args + argOffset); break; - case QUIT: + case EXIT: case UNDEFINED: return 0; } } + /* fromTime will be equal to the closest time to the target that is not before it. This just makes sure that + the time is correctly set to be the time of the next instruction. Trust me, it makes sense */ + *toTime = fromTime; } /* changes the camera to point to a txt file in the /Cameras directory, if such a file exists */ @@ -126,6 +103,12 @@ int fastForward(FILE* camera, unsigned long int currentTime, unsigned long int t /* returns: 1 if the camera has been changed, or 0 if it has not been changed */ int setCamera(char* name, FILE** camera){ char path[100]; /* stupidly long just in case */ + sprintf(path, "./Cameras/%s.txt", name); + FILE* temp = fopen(path, "r"); + if(temp == NULL)return 0; + if(*camera != NULL)fclose(*camera); + *camera = temp; + return 1; } /* Given a user-input string, will check if it is a valid command, and if so, execute it */ @@ -133,35 +116,60 @@ int setCamera(char* name, FILE** camera){ /* currentTime: the current game time. May be changed if the command requires it */ /* camera: the current event stream. May be changed if the command requires it */ /* paused: a boolean representing whether or not the output is paused. May be changed if the command requires it */ +/* returns: 1 if the program should continue, otherwise 0 */ int handleCommand(char* str, unsigned long int* currentTime, FILE** camera, int* paused){ - /* remember to pause before changing the camera */ - -} - -void delay(unsigned long int* currentTime, int* paused, unsigned long int seconds){ - /* do it with a for loop so that I can increment currentTime properly */ - for(int i = 0; i < seconds; i++){ - unsigned long int start = time(0); - while((time(0) - start < 1)) if(*paused) return; /* Will loop for 1 second */ - *currentTime++; /* increase the time by 1 */ + char* args; + InstructionMap inst = getInstruction(str); + + switch(inst.type){ + case PAUSE: + *paused = !*paused; + if(*paused) printf("Game is paused. Press enter to resume.\n"); + else printf("Game is unpaused. Resuming...\n"); + break; + case EXIT: + return 0; + case CHANGE_CAMERA: + if(setCamera(inst.args, camera)) + return fastForward(camera, 0, currentTime); + case LIST_CAMERAS: + printf("Valid cameras are: %s\n", CAMERA_LIST); + break; + case HELP: + printHelpText(); + break; + case UNDEFINED: + printf("That is not a valid instruction. Type \"help\" for a list of valid instructions.\n"); + break; + default: + printf("That instruction can not be triggered by the player. Type \"help\" for a list of valid instructions.\n"); } } -int readNextLine(int* currentTime, FILE** camera, int* paused){ - char* nextLineArgs; - InstructionType instType = getNextInstruction(*camera, &nextLineArgs); - switch(instType){ +/* Reads the next line in the event stream and executes its instruction */ +/* currentTime: the current game time */ +/* camera: the event stream in question */ +/* paused: boolean representing whether or not the output is paused */ +int readNextLine(unsigned long int* currentTime, FILE** camera, int* paused){ + char line[MAX_LINE_LENGTH]; + fgets(line, MAX_LINE_LENGTH, *camera); + + InstructionMap inst = getInstruction(line); + switch(inst.type){ case INSTANT_EVENT: - printf("%s", nextLineArgs); + printf("%s", inst.args); + // for(int i = 0; i < strlen(inst.args); i++)printf("%hu ", inst.args[i]); + // printf("\n"); break; case WAIT_ABSOLUTE: - delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(nextLineArgs, NULL)) - *currentTime); + delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(inst.args, NULL)) - *currentTime); break; case WAIT_RELATIVE: - delay(currentTime, paused, parseTimeString(nextLineArgs, NULL)); + delay(currentTime, paused, parseTimeString(inst.args, NULL)); break; - case QUIT: case UNDEFINED: + printf("Undefined instruction in event stream.\n"); + case EXIT: return 0; } return 1; @@ -175,20 +183,42 @@ typedef struct GameData{ void* outputThread(void* args){ GameData* gd = args; - unsigned long int* currentTime = args->currentTime; - FILE** camera = args->camera; - int* paused = args->paused; + unsigned long int* currentTime = gd->currentTime; + FILE** camera = gd->camera; + int* paused = gd->paused; + + /* if paused is true, then the || won't bother checking the other side, so readNextLine won't be executed */ while(*paused || readNextLine(currentTime, camera, paused)); + printf("The end! Exiting...\n"); + exit(0); } void* inputThread(void* args){ GameData* gd = args; - while() + unsigned long int* currentTime = gd->currentTime; + FILE** camera = gd->camera; + int* paused = gd->paused; + + char command[MAX_COMMAND_LENGTH]; + + while(handleCommand(fgets(command, MAX_COMMAND_LENGTH, stdin), currentTime, camera, paused)); + printf("Exit command recieved. Exiting...\n"); + exit(0); } int main(int argc, char* argv[]){ unsigned long int gameTime = 0; - FILE* camera; + FILE* camera = NULL; + /* Will only try to set the camera if there is a second argument */ + if(argc > 1 && !setCamera(argv[1], &camera)){ + printf("Invalid filename: %s. ", argv[1]); + }else{ + printf("Loading default camera: start\n"); + if(!setCamera("start", &camera)){ + printf("Default camera missing. Exiting...\n"); + exit(0); + } + } int paused = 0; GameData gameData = {&gameTime, &camera, &paused}; pthread_t inTh; @@ -197,5 +227,4 @@ int main(int argc, char* argv[]){ pthread_create(&outTh, NULL, outputThread, &gameData); pthread_join(inTh, NULL); pthread_join(outTh, NULL); - } From 4df374bd81407344f18923a541296b48663bf002 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 17 Jul 2016 23:03:51 -0400 Subject: [PATCH 15/18] System fully implemented! squashed some bugs. Not organized yet --- Cameras/test1.txt | 30 ++++++++++++++++++++++ Cameras/test2.txt | 30 ++++++++++++++++++++++ adventure | Bin 23856 -> 23856 bytes textAdventure.c | 63 ++++++++++++++++++++++++++++------------------ 4 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 Cameras/test1.txt create mode 100644 Cameras/test2.txt diff --git a/Cameras/test1.txt b/Cameras/test1.txt new file mode 100644 index 0000000..de9310c --- /dev/null +++ b/Cameras/test1.txt @@ -0,0 +1,30 @@ +i test1 seconds: 0 +oa 10 test1 seconds: 0 +wa 1 +i test1 seconds: 1 +oa 10 test1 seconds: 1 +wa 2 +i test1 seconds: 2 +oa 10 test1 seconds: 2 +wa 3 +i test1 seconds: 3 +oa 10 test1 seconds: 3 +wa 4 +i test1 seconds: 4 +oa 10 test1 seconds: 4 +wa 5 +i test1 seconds: 5 +oa 10 test1 seconds: 5 +wa 6 +i test1 seconds: 6 +oa 10 test1 seconds: 6 +wa 7 +i test1 seconds: 7 +oa 10 test1 seconds: 7 +wa 8 +i test1 seconds: 8 +oa 10 test1 seconds: 8 +wa 9 +i test1 seconds: 9 +oa 10 test1 seconds: 9 +q diff --git a/Cameras/test2.txt b/Cameras/test2.txt new file mode 100644 index 0000000..16c85c9 --- /dev/null +++ b/Cameras/test2.txt @@ -0,0 +1,30 @@ +i test2 seconds: 0 +oa 10 test2 seconds: 0 +wa 1 +i test2 seconds: 1 +oa 10 test2 seconds: 1 +wa 2 +i test2 seconds: 2 +oa 10 test2 seconds: 2 +wa 3 +i test2 seconds: 3 +oa 10 test2 seconds: 3 +wa 4 +i test2 seconds: 4 +oa 10 test2 seconds: 4 +wa 5 +i test2 seconds: 5 +oa 10 test2 seconds: 5 +wa 6 +i test2 seconds: 6 +oa 10 test2 seconds: 6 +wa 7 +i test2 seconds: 7 +oa 10 test2 seconds: 7 +wa 8 +i test2 seconds: 8 +oa 10 test2 seconds: 8 +wa 9 +i test2 seconds: 9 +oa 10 test2 seconds: 9 +q diff --git a/adventure b/adventure index 2051cfa316d562a18766ce070a96bc593418f249..6c94225e13e240541883208e5c11820947203ed1 100755 GIT binary patch delta 7526 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 *toTime) - printf("%s", inst.args + argOffset); + if(verifyTime(fromTime, parseTimeString(&inst.args)) > *toTime){ + printf("%s", inst.args); + } break; case ONGOING_EVENT_RELATIVE: - if(fromTime + parseTimeString(inst.args, &argOffset) > *toTime) - printf("%s", inst.args + argOffset); + if(fromTime + parseTimeString(&inst.args) > *toTime) + printf("%s", inst.args); break; - case EXIT: case UNDEFINED: - return 0; + printf("Undefined instruction in stream. Exiting...\n"); + exit(0); + case EXIT: + printf("Stream has already ended. Exiting...\n"); + exit(0); } } /* fromTime will be equal to the closest time to the target that is not before it. This just makes sure that @@ -103,7 +105,10 @@ int fastForward(FILE** camera, unsigned long int fromTime, unsigned long int* to /* returns: 1 if the camera has been changed, or 0 if it has not been changed */ int setCamera(char* name, FILE** camera){ char path[100]; /* stupidly long just in case */ + + if(name[strlen(name) - 1] == '\n') name[strlen(name) - 1] = '\0'; sprintf(path, "./Cameras/%s.txt", name); + FILE* temp = fopen(path, "r"); if(temp == NULL)return 0; if(*camera != NULL)fclose(*camera); @@ -152,6 +157,7 @@ int handleCommand(char* str, unsigned long int* currentTime, FILE** camera, int* /* paused: boolean representing whether or not the output is paused */ int readNextLine(unsigned long int* currentTime, FILE** camera, int* paused){ char line[MAX_LINE_LENGTH]; + memset(line, 0, MAX_LINE_LENGTH); fgets(line, MAX_LINE_LENGTH, *camera); InstructionMap inst = getInstruction(line); @@ -162,10 +168,10 @@ int readNextLine(unsigned long int* currentTime, FILE** camera, int* paused){ // printf("\n"); break; case WAIT_ABSOLUTE: - delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(inst.args, NULL)) - *currentTime); + delay(currentTime, paused, verifyTime(*currentTime, parseTimeString(&inst.args)) - *currentTime); break; case WAIT_RELATIVE: - delay(currentTime, paused, parseTimeString(inst.args, NULL)); + delay(currentTime, paused, parseTimeString(&inst.args)); break; case UNDEFINED: printf("Undefined instruction in event stream.\n"); @@ -201,7 +207,11 @@ void* inputThread(void* args){ char command[MAX_COMMAND_LENGTH]; - while(handleCommand(fgets(command, MAX_COMMAND_LENGTH, stdin), currentTime, camera, paused)); + while(1){ + memset(command, 0, MAX_COMMAND_LENGTH); + fgets(command, MAX_COMMAND_LENGTH, stdin); + if(handleCommand(command, currentTime, camera, paused) == 0) break; + } printf("Exit command recieved. Exiting...\n"); exit(0); } @@ -210,15 +220,18 @@ int main(int argc, char* argv[]){ unsigned long int gameTime = 0; FILE* camera = NULL; /* Will only try to set the camera if there is a second argument */ - if(argc > 1 && !setCamera(argv[1], &camera)){ - printf("Invalid filename: %s. ", argv[1]); + + if(argc > 1 && setCamera(argv[1], &camera)){ + printf("Loaded camera: %s\n", argv[1]); }else{ - printf("Loading default camera: start\n"); - if(!setCamera("start", &camera)){ - printf("Default camera missing. Exiting...\n"); + if(setCamera("start", &camera)){ + printf("Loaded default camera\n"); + }else{ + printf("Error: default camera is missing. Exiting..."); exit(0); } } + int paused = 0; GameData gameData = {&gameTime, &camera, &paused}; pthread_t inTh; From 5cbb371af646f06a1790f58846a7d8f9d6891c00 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 17 Jul 2016 23:52:19 -0400 Subject: [PATCH 16/18] Wrote an example camera! Readme will be written tomorrow --- Cameras/example1.txt | 14 ++++++++++++++ Cameras/example2.txt | 35 +++++++++++++++++++++++++++++++++++ adventure | Bin 23856 -> 23832 bytes textAdventure.c | 14 ++++++++++++-- 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 Cameras/example1.txt create mode 100644 Cameras/example2.txt diff --git a/Cameras/example1.txt b/Cameras/example1.txt new file mode 100644 index 0000000..720bd68 --- /dev/null +++ b/Cameras/example1.txt @@ -0,0 +1,14 @@ +wa 1 +i Hello! +wa 3 +i Welcome to the example! +wa 5 +i I just waited until the 5 second mark! This should have looked like two seconds to you. +wr 4 +i I just waited 4 seconds. +wa 10 +i This should pop up at the 10 second mark +wa 12 +i Let's change cameras +wa 15 +camera example2 diff --git a/Cameras/example2.txt b/Cameras/example2.txt new file mode 100644 index 0000000..b833172 --- /dev/null +++ b/Cameras/example2.txt @@ -0,0 +1,35 @@ +wa 1 +oa 20 this camera has been waiting for you for a while. 15 seconds, give or take. +i Waiting for camera to change +wa 5 +i Still waiting +wa 10 +i STIIIIIILLLL waiting +wa 15 +i Hello! This is a different camera! +wa 17 +i I can also pause your game. Behold! +p +i Welcome back! Sorry for pausing you so abruptly +wa 20 +i I can also pause your game without it telling you that it's paused, like so (press enter to continue): +ps +i Isn't that cool!? +wa 22 +i And unnecessary!? +wa 23 +i ... +wa 24 +i ... +wa 25 +i yes, it probably is +wa 27 +i ... +wa 29 +i ... +wa 31 +i Oh well, all's well that ends well. +wa 33 +i Such as this game +wa 34 +q diff --git a/adventure b/adventure index 6c94225e13e240541883208e5c11820947203ed1..7a423a1523f5afb714a0497188e51760de2aed70 100755 GIT binary patch delta 4578 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 delta 4355 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 Date: Sun, 17 Jul 2016 23:57:44 -0400 Subject: [PATCH 17/18] returned at the end of main --- textAdventure.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/textAdventure.c b/textAdventure.c index d0c80d7..c8f329a 100644 --- a/textAdventure.c +++ b/textAdventure.c @@ -250,4 +250,6 @@ int main(int argc, char* argv[]){ pthread_create(&outTh, NULL, outputThread, &gameData); pthread_join(inTh, NULL); pthread_join(outTh, NULL); + + return 0; } From 4ad4e68a6e310e39f75142a12ef5f3a4f5811c1a Mon Sep 17 00:00:00 2001 From: HarryNews Date: Mon, 18 Jul 2016 19:13:27 -0400 Subject: [PATCH 18/18] Added README.md --- README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..663db16 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +Hello! This is my final project. +If you plan on writing a game in this, you should definitely read the "issues" section on the bottom of this readme +#Playing a game +The game consists of a series of messages that print out at specific times. The messages change depending on which "camera" the user is looking through. To start the game with the default camera, launch the game normally. To start the game with a different camera, launch the game with the camera's name as an argument. +##Commands +The player interacts with the game using commands. Although not required, before writing a command, press enter to pause the messages, then write the command, then press enter again to unpause them. The commands are as follows. +### Pausing the game +To pause the game, press enter +### Changing the camera +To change the camera, type `"camera "` +To get a list of available cameras, type "cameras" +### Listing the commands +To get a list of commands, type "help" +### Quitting +To quit, type "quit" +# Writing a game! +## Events! +### Instant Events + To print a line of text to the screen, use an instant event. It will only print if the player is using the camera that the event is declared on when it is scheduled to print + to write an instant event, use `i ` +### Ongoing Events + Ongoing events are events that are carried out over time. They will only print if the player switches to the camera that they are declared on after they are scheduled to start and before they are scheduled to end. + + There are two different ways to specify the duration of the event. The first is telling it the time that it will end. + To do so, use `oa