#include #include #include #include #include "expression.h" union expression* webdice_const(int64_t value){ union expression* aux = (union expression*) malloc(sizeof(union expression)); (*aux).constant.id = WEBDICE_CONST; (*aux).constant.value = value; return aux; } union expression* webdice_roll(int64_t count, int64_t roll){ union expression* aux = (union expression*) malloc(sizeof(union expression)); (*aux).roll.id = WEBDICE_ROLL; (*aux).roll.count = count; (*aux).roll.type = roll; return aux; } union expression* webdice_binary(enum binary_type type, union expression* left, union expression* right){ union expression* aux = (union expression*) malloc(sizeof(union expression)); (*aux).binary.id = WEBDICE_BINARY; (*aux).binary.operation = type; (*aux).binary.left = left; (*aux).binary.right = right; return aux; } union expression* webdice_mul(union expression* left, union expression* right){ return webdice_binary(WEBDICE_MUL,left,right); } union expression* webdice_div(union expression* left, union expression* right){ return webdice_binary(WEBDICE_DIV,left,right); } union expression* webdice_add(union expression* left, union expression* right){ return webdice_binary(WEBDICE_ADD,left,right); } union expression* webdice_sub(union expression* left, union expression* right){ return webdice_binary(WEBDICE_SUB,left,right); } struct expression_result resolve(union expression* root){ struct expression_result result,left,right; int i, j; int64_t *values = NULL; int64_t total; long double size; int64_t length = 1; switch((*root).id.id){ case WEBDICE_CONST: size = log10l((*root).constant.value); length += (int64_t) ceill(size); result.min = (*root).constant.value; result.max = (*root).constant.value; result.expected = (*root).constant.value; result.actual = (*root).constant.value; result.text = (char*) malloc(length * sizeof(char)); sprintf(result.text, "%lld",(*root).constant.value); break; case WEBDICE_ROLL: size = (*root).roll.count * ceill(15+log10l((*root).roll.count * (*root).roll.type)); length += (int64_t) size; result.min = (*root).roll.count; result.max = (*root).roll.count * (*root).roll.type; result.expected = (*root).roll.count * ((*root).roll.type + 1.0) / 2.0; result.text = (char*) malloc(length * sizeof(char)); fprintf(stderr,"COUNT: %lld\n\n",(*root).roll.count); values = (int64_t*) malloc((*root).roll.count * sizeof(int64_t)); fprintf(stderr,"ALLOC'D %X\n\n",values); for (i = 0, j = (*root).roll.count, total = 0; i < (*root).roll.count; i++, j--){ values[i] = 1 + (rand() % (*root).roll.type); total += values[i]; if (i == 0 && j == 1){ sprintf(result.text,"%lld", (*root).roll.count, (*root).roll.type, values[i], total); }else if (i == 0){ sprintf(result.text,"%lld", values[i], total); }else{ sprintf(&(result.text[strlen(result.text)]),"%lld,", values[i]); } } fprintf(stderr,"FREE'D %X\n\n",values); fprintf(stderr,"FREE'D %X\n\n",values); fprintf(stderr,"FREE'D %X\n\n",values); fflush(stderr); free(values); fprintf(stderr,"FREE'D %X\n\n",values); result.actual = total; break; case WEBDICE_BINARY: left = resolve((*root).binary.left); right = resolve((*root).binary.right); length += 5 + strlen(left.text) + strlen(right.text); result.text = (char*) malloc(length * sizeof(char)); switch((*root).binary.operation){ case WEBDICE_MUL: result.min = left.min * right.min; result.max = left.max * right.max; result.expected = left.expected * right.expected; result.actual = left.actual * right.actual; sprintf(result.text,"(%s * %s)",left.text,right.text); break; case WEBDICE_DIV: result.min = left.min / right.max; result.max = left.max / right.min; result.expected = left.expected / right.expected; result.actual = left.actual / right.actual; sprintf(result.text,"(%s / %s)",left.text,right.text); break; case WEBDICE_ADD: result.min = left.min + right.min; result.max = left.max + right.max; result.expected = left.expected + right.expected; result.actual = left.actual + right.actual; sprintf(result.text,"(%s + %s)",left.text,right.text); break; case WEBDICE_SUB: result.min = left.min - right.max; result.max = left.max - right.min; result.expected = left.expected - right.expected; result.actual = left.actual - right.actual; sprintf(result.text,"(%s - %s)",left.text,right.text); break; default: free(result.text); result.text = NULL; result.min = 0; result.max = 0; result.expected = 0; result.actual = 0; break; } free(left.text); free(right.text); break; default: result.text = NULL; result.min = 0; result.max = 0; result.expected = 0; result.actual = 0; break; } return result; } void free_expression(union expression* root){ switch((*root).id.id){ case WEBDICE_BINARY: free_expression((*root).binary.left); free_expression((*root).binary.right); case WEBDICE_CONST: case WEBDICE_ROLL: default: free(root); break; } return; }