/* Tests expressions and their evaluation */ void test_expressions() { expression_t* ex1 = malloc(sizeof(expression_t)); expression_t* ex2 = malloc(sizeof(expression_t)); expression_t* ex3 = malloc(sizeof(expression_t)); expression_t* ex4 = malloc(sizeof(expression_t)); ex1->next = ex2; ex2->next = ex3; ex3->next = ex4; /* trying successful evaluation first */ ex1->type = EXP_NUMBER | '+'; ex1->data.number = 14; ex2->type = EXP_NUMBER | '-'; ex2->data.number = 4; ex3->type = EXP_NUMBER | '/'; ex3->data.number = 2; ex4->type = EXP_NUMBER | '*'; ex4->data.number = 3; ulong result; assert(!expression_evaluate(&ex1, &result)); assert(result == 15); assert(ex1 == 0); /* trying unsuccessful evaluation */ ex1 = malloc(sizeof(expression_t)); ex2 = malloc(sizeof(expression_t)); ex3 = malloc(sizeof(expression_t)); ex4 = malloc(sizeof(expression_t)); ex1->next = ex2; ex2->next = ex3; ex3->next = ex4; ex1->type = EXP_NUMBER | '+'; ex1->data.number = 14; ex2->type = EXP_NUMBER | '-'; ex2->data.number = 4; ex3->type = EXP_NUMBER | '/'; ex3->data.number = 2; ex4->type = EXP_LABEL; ex4->data.label = "impossible to find label"; assert(expression_evaluate(&ex1, &result)); assert(result == 5); assert(ex1 == ex4); fprintf(stdout, "%s:\tpassed\n", __FUNCTION__); }
void update(objectmachine_t *obj, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectdecorator_t *dec = (objectdecorator_t*)obj; objectmachine_t *decorated_machine = dec->decorated_machine; objectdecorator_setscale_t *me = (objectdecorator_setscale_t*)obj; object_t *object = obj->get_object_instance(obj); float scale_x = max(0.0f, expression_evaluate(me->scale_x)); float scale_y = max(0.0f, expression_evaluate(me->scale_y)); object->actor->scale = v2d_new(scale_x, scale_y); decorated_machine->update(decorated_machine, team, team_size, brick_list, item_list, object_list); }
void update(objectmachine_t *obj, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectdecorator_t *dec = (objectdecorator_t*)obj; objectmachine_t *decorated_machine = dec->decorated_machine; objectdecorator_setplayerposition_t *me = (objectdecorator_setplayerposition_t*)obj; object_t *object = obj->get_object_instance(obj); player_t *player = enemy_get_observed_player(object); v2d_t offset = v2d_new(expression_evaluate(me->offset_x), expression_evaluate(me->offset_y)); player->actor->position = v2d_add(object->actor->position, offset); player->disable_wall = PLAYER_WALL_NONE; decorated_machine->update(decorated_machine, team, team_size, brick_list, item_list, object_list); }
/* private strategies */ void createchild_strategy(objectdecorator_children_t *me, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectmachine_t *obj = (objectmachine_t*)me; object_t *object = obj->get_object_instance(obj); object_t *child; v2d_t offset; offset.x = expression_evaluate(me->offset_x); offset.y = expression_evaluate(me->offset_y); child = level_create_enemy(me->object_name, v2d_add(object->actor->position, offset)); if(child != NULL) { enemy_add_child(object, me->child_name, child); enemy_update(child, team, team_size, brick_list, item_list, object_list); /* important to exchange data between objects */ nanocalcext_set_target_object(object, brick_list, item_list, object_list); /* restore nanocalc's target object */ } }
void update(objectmachine_t *obj, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectdecorator_t *dec = (objectdecorator_t*)obj; objectdecorator_enemy_t *me = (objectdecorator_enemy_t*)obj; objectmachine_t *decorated_machine = dec->decorated_machine; object_t *object = obj->get_object_instance(obj); int i, score; score = (int)expression_evaluate(me->score); /* player x object collision */ for(i=0; i<team_size; i++) { player_t *player = team[i]; if(actor_pixelperfect_collision(object->actor, player->actor)) { if(player_is_attacking(player) || player->invincible) { /* I've been defeated */ player_bounce(player, object->actor); level_add_to_score(score); level_create_item(IT_EXPLOSION, v2d_add(object->actor->position, v2d_new(0,-15))); level_create_animal(object->actor->position); sound_play( soundfactory_get("destroy") ); object->state = ES_DEAD; } else { /* The player has been hit by me */ player_hit(player, object->actor); } } } decorated_machine->update(decorated_machine, team, team_size, brick_list, item_list, object_list); }
// returns the result of the arithmetic expression_t (expanding subexpressions) static double op_arithmetic(expression_t *expr) { double num1 = 0; expression_operand_t *op1; double res = -1; int offset = 0; char op = expr->operation->op; expression_operand_t **operands = expr->operands; // iterate over the NULL-terminated array of operands while(operands[offset] != NULL) { op1 = operands[offset]; switch(op1->type) { case EXPR_OPTYPE_CALLBACK: num1 = op1->callback.cb(op1->callback.user); expression_callback_change_value(op1, num1); //op1->callback.lastCall = time(NULL); break; case EXPR_OPTYPE_EXPRESSION: // evaluate sub expression_t (recursion happens here) num1 = expression_evaluate(op1->expr); if(num1 < 0) return -1; break; case EXPR_OPTYPE_INTEGER: num1 = (double)op1->inum; break; case EXPR_OPTYPE_FLOAT: num1 = (double)op1->fnum; break; case EXPR_OPTYPE_STRING: if(sscanf(op1->string, "%lf", &num1) != 1) { fprintf(stderr, "op_arithmetic() : accepts only numeric values (no strings)\n"); return -1; } break; default: fprintf(stderr, "op_boolean() : Uknown operand type: 0x%02x\n", op1->type); return -1; } if(offset == 0) { if (expr->operation->minOperands == 1 && expr->operation->maxOperands == 1) res = _do_arithmetic(op, num1, 0); else res = num1; } else { res = _do_arithmetic(op, (double)res, num1); } offset++; } return res; }
void update(objectmachine_t *obj, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectdecorator_t *dec = (objectdecorator_t*)obj; objectmachine_t *decorated_machine = dec->decorated_machine; objectdecorator_addlives_t *me = (objectdecorator_addlives_t*)obj; player_set_lives( player_get_lives() + (int)expression_evaluate(me->lives) ); decorated_machine->update(decorated_machine, team, team_size, brick_list, item_list, object_list); }
void update(objectmachine_t *obj, player_t **team, int team_size, brick_list_t *brick_list, item_list_t *item_list, object_list_t *object_list) { objectdecorator_t *dec = (objectdecorator_t*)obj; objectmachine_t *decorated_machine = dec->decorated_machine; objectdecorator_textout_t *me = (objectdecorator_textout_t*)obj; object_t *object = obj->get_object_instance(obj); symboltable_t *st = objectvm_get_symbol_table(object->vm); char *processed_text; int start, length; float wpx; v2d_t pos; /* 문자열의 범위를 계산한다 ( clip()할 필요가 없다 ) */ start = (int)expression_evaluate(me->index_of_first_char); length = (int)expression_evaluate(me->length); /* 글꼴 구성 */ font_use_substring(me->fnt, start, length); font_set_width(me->fnt, (int)expression_evaluate(me->max_width)); /* 글꼴 텍스트 */ processed_text = nanocalc_interpolate_string(me->text, st); font_set_text(me->fnt, "%s", processed_text); free(processed_text); /* symbol table tricks */ symboltable_set(st, "$_STRLEN", tagged_strlen(font_get_text(me->fnt))); /* $_STRLEN의 텍스트 길이를 저장한다. */ /* 글꼴 위치 */ pos = v2d_new(expression_evaluate(me->xpos), expression_evaluate(me->ypos)); wpx = font_get_textsize(me->fnt).x; switch(me->style) { case TEXTOUT_LEFT: break; case TEXTOUT_CENTRE: pos.x -= wpx/2; break; case TEXTOUT_RIGHT: pos.x -= wpx; break; } font_set_position(me->fnt, v2d_add(object->actor->position, pos)); /* done! */ decorated_machine->update(decorated_machine, team, team_size, brick_list, item_list, object_list); }
void get_rectangle_coordinates(objectdecorator_lockcamera_t *me, int *x1, int *y1, int *x2, int *y2) { int mi, ma; *x1 = (int)expression_evaluate(me->x1); *x2 = (int)expression_evaluate(me->x2); *y1 = (int)expression_evaluate(me->y1); *y2 = (int)expression_evaluate(me->y2); if(*x1 == *x2) (*x2)++; if(*y1 == *y2) (*y2)++; mi = min(*x1, *x2); ma = max(*x1, *x2); *x1 = mi; *x2 = ma; mi = min(*y1, *y2); ma = max(*y1, *y2); *y1 = mi; *y2 = ma; }
void expression_simplify(EXPRESSION expression) { if(expression[0].type == END || expression[1].type == END) return; int i = 0, j, n; int type; double value; // fudge to make a non-allocated 2x1 matrix act like an allocated one double work[2], *p_work[2]; p_work[0] = &work[0]; p_work[1] = &work[1]; // loop until a pass is completed with no simplifications do { // start at the begining haveing done no simplifications i = n = 0; while(1) { // find the next value-value-operator pattern while(!(expression[i].type == VALUE && expression[i+1].type == VALUE && IS_OPERATOR(expression[i+2].type)) && expression[i+2].type != END) i ++; // reached the end if(expression[i+2].type == END) break; // evaluate the sub-expression type = expression[i+3].type; expression[i+3].type = END; expression_evaluate(1, &value, &expression[i], NULL, p_work); expression[i+3].type = type; // replace the sub-expression with the value expression[i].value = value; j = i + 3; while(expression[j-1].type != END) { expression[j-2] = expression[j]; j ++; } // increment the number of simplifications n ++; } } while(n); }
static int check_division(expression_t *expr) { double test = 1; expression_operand_t *op1 = expr->operands[1]; if(!check_arithmetic(expr)) return 0; if(!op1) return 0; switch(op1->type) { case EXPR_OPTYPE_STRING: if(sscanf(op1->string, "%lf", &test) != 1) { fprintf(stderr, "op_arithmetic() : accepts only numeric values (no strings)\n"); return 0; } break; case EXPR_OPTYPE_INTEGER: test = (double)op1->inum; break; case EXPR_OPTYPE_FLOAT: test = op1->fnum; break; case EXPR_OPTYPE_CALLBACK: test = op1->callback.cb(op1->callback.user); expression_callback_change_value(op1, test); //op1->callback.lastCall = time(NULL); break; case EXPR_OPTYPE_EXPRESSION: // evaluate sub expression_t (recursion happens here) test = expression_evaluate(op1->expr); if(test == -1) // abort if we have an invalid subexpression as divisor return 0; break; } if(test == 0) // division is not valid if the divisor is 0 return 0; return 1; }
static double op_change(expression_t *expr) { double period = 1.0; struct timeval now; gettimeofday(&now, NULL); expression_operand_t *op1 = expr->operands[0]; if(expr->numOperands == 2) { expression_operand_t *op2 = expr->operands[1]; switch(op2->type) { case EXPR_OPTYPE_INTEGER: period = (double)op2->inum; break; case EXPR_OPTYPE_FLOAT: period = op2->fnum; break; case EXPR_OPTYPE_STRING: if(sscanf(op2->string, "%lf", &period) != 1) { fprintf(stderr, "'%s' string doesn't represent an integer", op2->string); return 0; } break; case EXPR_OPTYPE_CALLBACK: period = op2->callback.cb(op2->callback.user); break; case EXPR_OPTYPE_EXPRESSION: period = expression_evaluate(op2->expr); break; default: return 0; } } double diff = (now.tv_sec - op1->callback.lastChange.tv_sec) + ((now.tv_usec - op1->callback.lastChange.tv_usec) / 1e6); return (double)(diff <= period); }
static CMDERR internal_parse_command(const char *original_command, int execute) { char command[MAX_COMMAND_LENGTH], parens[MAX_COMMAND_LENGTH]; char *params[MAX_COMMAND_PARAMS]; CMDERR result = CMDERR_NONE; char *command_start; char *p, c = 0; /* make a copy of the command */ strcpy(command, original_command); /* loop over all semicolon-separated stuff */ for (p = command; *p != 0; ) { int paramcount = 0, foundend = FALSE, instring = FALSE, isexpr = FALSE, parendex = 0; /* find a semicolon or the end */ for (params[paramcount++] = p; !foundend; p++) { c = *p; if (instring) { if (c == '"' && p[-1] != '\\') instring = FALSE; } else { switch (c) { case '"': instring = TRUE; break; case '(': case '[': case '{': parens[parendex++] = c; break; case ')': if (parendex == 0 || parens[--parendex] != '(') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break; case ']': if (parendex == 0 || parens[--parendex] != '[') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break; case '}': if (parendex == 0 || parens[--parendex] != '{') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break; case ',': if (parendex == 0) params[paramcount++] = p; break; case ';': if (parendex == 0) foundend = TRUE; break; case '-': if (parendex == 0 && paramcount == 1 && p[1] == '-') isexpr = TRUE; *p = c; break; case '+': if (parendex == 0 && paramcount == 1 && p[1] == '+') isexpr = TRUE; *p = c; break; case '=': if (parendex == 0 && paramcount == 1) isexpr = TRUE; *p = c; break; case 0: foundend = TRUE; break; default: *p = tolower(c); break; } } } /* check for unbalanced parentheses or quotes */ if (instring) return MAKE_CMDERR_UNBALANCED_QUOTES(p - command); if (parendex != 0) return MAKE_CMDERR_UNBALANCED_PARENS(p - command); /* NULL-terminate if we ended in a semicolon */ p--; if (c == ';') *p++ = 0; /* process the command */ command_start = params[0]; /* allow for "do" commands */ if (tolower(command_start[0] == 'd') && tolower(command_start[1] == 'o') && isspace(command_start[2])) { isexpr = TRUE; command_start += 3; } /* if it smells like an assignment expression, treat it as such */ if (isexpr && paramcount == 1) { UINT64 expresult; EXPRERR exprerr = expression_evaluate(command_start, debug_get_cpu_info(cpu_getactivecpu())->symtable, &expresult); if (exprerr != EXPRERR_NONE) return MAKE_CMDERR_EXPRESSION_ERROR(EXPRERR_ERROR_OFFSET(exprerr)); } else { result = internal_execute_command(execute, paramcount, ¶ms[0]); if (result != CMDERR_NONE) return MAKE_CMDERR(CMDERR_ERROR_CLASS(result), command_start - command); } } return CMDERR_NONE; }
void set_yspeed(player_t *player, expression_t *speed) { player->actor->speed.y = expression_evaluate(speed); }
// returns -1 on error 0 if FALSE 1 if TRUE static double op_boolean(expression_t *expr) { double num1 = 0; char str1[EXPR_STRING_OPERAND_MAX_SIZE]; char str_prev[EXPR_STRING_OPERAND_MAX_SIZE]; expression_operand_t *op1; double res = 0; int offset = 0; int is_integer = 0; char op = expr->operation->op; expression_operand_t **operands = expr->operands; // iterate over the NULL-terminated array of operands while(operands[offset] != NULL) { op1 = operands[offset]; switch(op1->type) { case EXPR_OPTYPE_CALLBACK: num1 = op1->callback.cb(op1->callback.user); expression_callback_change_value(op1, num1); //op1->callback.lastCall = time(NULL); sprintf(str1, "%lf", num1); break; case EXPR_OPTYPE_EXPRESSION: // evaluate sub expression_t (recursion happens here) num1 = expression_evaluate(op1->expr); sprintf(str1, "%lf", num1); break; case EXPR_OPTYPE_INTEGER: num1 = (double)op1->inum; sprintf(str1, "%lf", num1); break; case EXPR_OPTYPE_FLOAT: num1 = op1->fnum; sprintf(str1, "%lf", num1); break; case EXPR_OPTYPE_STRING: snprintf(str1, sizeof(str1), "%s", op1->string); if(sscanf(str1, "%lf", &num1) != 1) num1 = str1[0]?1:0; else is_integer = 1; break; default: fprintf(stderr, "op_boolean() : Uknown operand type: 0x%02x\n", op1->type); return 0; } if(op == EXPR_OP_TEST) return (num1?1:0); else if(op == EXPR_OP_NOT) return (num1?0:1); if(offset == 0) { res = num1; strcpy(str_prev, str1); // save the string counterpart of the 'res' variable } else { if(op1->type == EXPR_OPTYPE_STRING && !is_integer) { res = (double)_do_str_boolean(op, str_prev, str1); sprintf(str_prev, "%f", res); } else { res = _do_number_boolean(op, res, num1); sprintf(str_prev, "%f", res); } } offset++; } return res; }