Topple/Topple 1/Source (C99)

From Esolang
Jump to navigation Jump to search

←Back

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

#define MAX_SIZE 4097   // Max amount of vals, vars, etc. Currently the best way I know to do this.

#define CLEAR() printf("\e[1;1H\e[2J");

typedef struct variables{
    char name;
    char val;
} var;

char vals[MAX_SIZE];    // Admitted Values
var vars[MAX_SIZE];     // Variables

int nest = 0;           // Keeps track of nested IFs, FORs, etc. while processing them. Ensures that code outside of an IF or FOR is not included
int ifRun = 1;          // Bool, If 0, ELSE code will run. Otherwise, nothing happens.
int commenting = 0;     // Bool, Allows for commenting w/ proper punctuation

char input;

long long timeInMilliseconds(void) { // Returns the current time in milliseconds
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);
}

int fileSize(char *stream){ // Returns the size (# of chars) of a file
    FILE* file = fopen(stream,"r");
    
    int size=0;
    char ch;
    
    while ( (ch = fgetc(file)) != EOF ) size++;
    
    fclose(file);
    return size;
}

void readFile(char *stream, char toFile[]){ // Copies the contents of a file into a given variable
    FILE* file = fopen(stream,"r");
    
    char ch;
    
    int i=0;
    while ( (ch = fgetc(file)) != EOF ) {
        toFile[i]=ch;
        i++;
    }
    
    fclose(file);
}

char proCon(char In[], int size) { // Process Console
    int skip=0;
	for(int i = 0; i <= size; i++) { // Skips characters used in an IF, ELSE, or FOR
		if(!commenting) {
			if(skip) {
				skip--;
				continue;
			}

			if(In[i]=='.') { // "Admits" a given character
				for(int j = 0; j<MAX_SIZE; j++) {
					if(vals[j] == '\0') {
						if(In[i-1] == '\\') {
							vals[j] = '\n';

						} else if(In[i-1] == '!') { // Takes User Input
							scanf(" %c",&input);
							vals[j] = input;

						} else if(In[i-1]=='?') { // IF statement
							for(int j = 0; j < MAX_SIZE; j++) {
								if(vals[j]=='\0') {
									if(vals[j-2]==vals[j-1]) { // Compares last two given vals
										vals[j-2] = '1'; // True
									} else {
										vals[j-2] = '0'; // False
									}

									vals[j-1] = '\0';
									break;
								}
							}

						} else if(In[i-1]=='#') { // Returns a random number (0 - 9)

							srand(timeInMilliseconds()); // Sets seed for the random stuff
							int num1=rand()%10;
							int num2=num1;
							while(num1 == num2) { // Continuously randomizing num1 until it is no longer the same as num2.
								srand(timeInMilliseconds());
								num1 = rand()%10;
							}

							vals[j] = num1+'0';
							break;

						} else if(In[i-1]=='^') { // Calls variables
							for(int j = 0; j<MAX_SIZE; j++) {
								if(vars[j].name==In[i-2]) {
									for(int k = 0; k<MAX_SIZE; k++) {
										if(vals[k]=='\0') {
											vals[k] = vars[j].val;
											break;
										}
									}
									break;
								}
							}
						} else {
							vals[j] = In[i-1];
						}

						break;
					}
				}
			}


			if(In[i]==',') { // Output characters w/o admitting them
				if(In[i-1]=='\\') {
					printf("\n");
				} else {
					printf("%c",In[i-1]);
				}

			} else if(In[i-1]=='<') { // FOR Loop, loops a given number of times
				nest++;
				int r=0;
				for(int j = 0; j < MAX_SIZE; j++) {
					if(vals[j] == '\0') {
						r = vals[j-1]-'0';
						vals[j-1]='\0';
						break;
					}
				}

				char subCon[MAX_SIZE];
				for(int k = 0; k<MAX_SIZE; k++) subCon[k]='\0';

				for(int j = 0; In[i+j]!='\0'; j++) {
					if(In[i+j]=='<') nest++;
					if(In[i+j]=='>') nest--;


					if(!nest) break;

					subCon[j] = In[i+j];
					skip++;
				}

				for(int j = 0; j < r; j++) {
					proCon(subCon,strlen(subCon));
				}

			} else if(In[i-1]=='(') { // IF Statement, runs if the last admitted character is non-zero
				int condition=0;
				nest++;
				for(int j = 0; j < MAX_SIZE; j++) { // Finds last admitted character and checks if it's a non-zero value.
					if(vals[j] == '\0') {
						condition = (vals[j-1]!='0');
						vals[j-1] = '\0';
						break;
					}
				}

				char subCon[MAX_SIZE];
				for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0';

				for(int j = 0; In[i+j]!='\0'; j++) {
					if(In[i+j]=='(') nest++;
					if(In[i+j]==')') nest--;
					if(!nest) {
						skip+=j+1;
						break;
					}
					subCon[j] = In[i+j];
				}

				if(condition) {
					proCon(subCon,strlen(subCon));
					ifRun=1;
				} else {
					ifRun=0;
				}

			} else if(In[i-1]=='[') { // ELSE Statement. If the last IF or WHILE Statement did not run, this will run in place of it.
				nest++;

				char subCon[MAX_SIZE];
				for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0';

				for(int j = 0; In[i+j]!='\0'; j++) {
					if(In[i+j]=='[') nest++;
					if(In[i+j]==']') nest--;
					if(!nest) {
						skip+=j+1;
						break;
					}
					subCon[j] = In[i+j];
				}
				if(!ifRun) {
					proCon(subCon,strlen(subCon));
					ifRun=1;
				}

			} else if(In[i-1]=='{') { // WHILE loop, loops for as long as a given variable is non-zero
			    char condLoc; // Condition location
				char condition;
				nest++;
				
				for(int j=0; j<MAX_SIZE; j++){
				    if(vals[j]=='\0'){
				        condLoc=vals[j-1];
				        vals[j-1]='\0';
				        break;
				    }
				}

				char subCon[MAX_SIZE];
				for(int j = 0; j<MAX_SIZE; j++) subCon[j]='\0';

				for(int j = 0; In[i+j]!='\0'; j++) {
					if(In[i+j]=='{') nest++;
					if(In[i+j]=='}') nest--;
					if(!nest) {
						break;
					}
					skip++;
					subCon[j] = In[i+j];
				}
				while(1) {
				    for(int j = 0; j<MAX_SIZE; j++) {
    					if(vars[j].name==condLoc) {
    						condition = vars[j].val-'0';
    						break;
    					}
				    }
				    
					if(!condition) {
						break;
					} else {
						proCon(subCon,strlen(subCon));
					}
					

				}


			} else if(In[i-1]=='@') { // Outputs all admitted characters, then clears
				for(int j = 0; j<MAX_SIZE; j++) {
				    if(vals[j]=='\\') printf("\n");
					printf("%c",vals[j]);
					vals[j] = '\0';
				}
			} else if(In[i-1]=='&') { // Outputs all admitted characters w/o clearing
				for(int j = 0; j<MAX_SIZE; j++) {
					printf("%c",vals[j]);
				}

			} else if(In[i-1]=='|') { // Clears all admitted data
				for(int j = 0; j<MAX_SIZE; j++)
					vals[j] = '\0';


			} else if(In[i-1]==':') { // Outputs admitted character at a given index
				vals[In[i-2]-'0'] = '\0';
				for(int j = In[i-2]-'0'; j < MAX_SIZE; j++) vals[j]=vals[j+1];
				
			} else if(In[i-1]==';') { //  Pulls an admitted value from a given index and admits it again
				for(int j = 0; j < MAX_SIZE; j++){
				    if(vals[j]=='\0'){
				        vals[j] = vals[In[i-2]-'0'];
				        break;
				    }
				}
			
			} else if(In[i-1]=='=') { // Defines variables
				for(int j = 0; j<MAX_SIZE; j++) {
					if(vars[j].name=='\0' || vars[j].name==In[i-2]) {
						vars[j].name = In[i-2];
						vars[j].val = In[i];
						break;
					}
				}
				
			} else if(In[i-1]=='^') {
				if(In[i]=='+'){
				    skip++;
				    for(int j=0; j<MAX_SIZE; j++)
				        if(vars[j].name==In[i-2]) vars[j].val++;
				}else if(In[i]=='-'){
				    skip++;
				    for(int j=0; j<MAX_SIZE; j++)
				        if(vars[j].name==In[i-2]) vars[j].val--;
				}
				
			} else if(In[i-1]=='~') { // Clears console
				CLEAR();

			} else if(In[i-1]=='*') { // Quits the program
			    exit(0);
			}
		}
		if(In[i]=='_') { // Toggles commenting
			commenting = !commenting;
		}

	}

}

int main() {
	for(int i = 0; i < MAX_SIZE; i++) { // Clears values and variables before use
		vals[i] = '\0';
	}
	int size = fileSize("main.txt");
	char console[size]; // The console... who coulda guessed?
	for(int i=0; i<size; i++) console[i]='\0';
	readFile("main.txt",console);
	proCon(console,size);

	return 0;
}