char * power (char *str, expr_t *e) { expr_t e2; str = factor (str, e); while (str[0] == '!') { str++; makeexp (e, FAC, *e, NULL); } str = skipspace (str); if (str[0] == '^') { str = power (str + 1, &e2); makeexp (e, POW, *e, e2); } return str; }
int main(int argc, char* argv[]) { initscr(); scrollok(stdscr, TRUE); wprintw(stdscr, "Welcome to Scripted ver. %d.%d for the Brave Quest engine.\nCopyright 2012 Mad Science Inc.\nPlease do not redistrubute.\n",scriptedvernum,scriptedvernum2); stufffilename(); if(loadscript(filename) == 1) { wprintw(stdscr, "File not Found. Would you like to make a new file?\n"); if(bie() == 'y') { cleanfilebuff(); if(savescript(filename) == 1) { wprintw(stdscr, "Your disk sucks.\n"); bi(); return 1; } } else { wprintw(stdscr, "Goodbye.\n"); endwin(); return 1; } } currlinenum = linenum; menu(); wprintw(stdscr, "Press escape to go to the save menu\n"); for(;;) { wprintw(stdscr, "q= give, w= take, e= say, r= flag, t= move, y= battle, u= check flag, i= check item, o= party add, p= party remove, [ = check character\n"); wprintw(stdscr, "a= warp, s= check experience, d= give experience, f= make experience, g= exec script, h= screen effect, j= user input, k= goline, l= make health\n"); wprintw(stdscr, "b= check stat, n= make stat, m= blank, ,= show line, .= change line.\n"); input[0] = bie(); if(input[0] == 27) menu(); if(input[0] == 'q') give(); if(input[0] == 'w') take(); if(input[0] == 'e') say(); if(input[0] == 'r') flag(); if(input[0] == 't') mmove(); if(input[0] == 'y') battle(); if(input[0] == 'u') checkflag(); if(input[0] == 'i') checkitem(); if(input[0] == 'o') partyadd(); if(input[0] == 'p') partyrm(); if(input[0] == '[') checkparty(); if(input[0] == 'a') warp(); if(input[0] == 's') checkexp(); if(input[0] == 'd') giveexp(); if(input[0] == 'f') makeexp(); if(input[0] == 'g') execscript(); if(input[0] == 'h') screeneffect(); if(input[0] == 'j') userinput(); if(input[0] == 'k') goline(); if(input[0] == 'l') makehealth(); if(input[0] == 'z') teachspell(); if(input[0] == 'x') unlearnspell(); if(input[0] == 'b') checkstat(); if(input[0] == 'n') makestat(); if(input[0] == 'm') blank(); if(input[0] == ',') showline(); if(input[0] == '.') changeline(); if(currlinenum > linenum) linenum = currlinenum; } return 0; };
/* Evaluate the expression E and put the result in R. */ void mpz_eval_expr (mpz_ptr r, expr_t e) { mpz_t lhs, rhs; switch (e->op) { case LIT: mpz_set (r, e->operands.val); return; case PLUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_add (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MINUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_sub (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MULT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_mul (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case DIV: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_q (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MOD: mpz_init (rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_abs (rhs, rhs); mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); mpz_clear (rhs); return; case REM: /* Check if lhs operand is POW expression and optimize for that case. */ if (e->operands.ops.lhs->op == POW) { mpz_t powlhs, powrhs; mpz_init (powlhs); mpz_init (powrhs); mpz_init (rhs); mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_powm (r, powlhs, powrhs, rhs); if (mpz_cmp_si (rhs, 0L) < 0) mpz_neg (r, r); mpz_clear (powlhs); mpz_clear (powrhs); mpz_clear (rhs); return; } mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_r (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION >= 2 case INVMOD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_invert (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case POW: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmpabs_ui (lhs, 1) <= 0) { /* For 0^rhs and 1^rhs, we just need to verify that rhs is well-defined. For (-1)^rhs we need to determine (rhs mod 2). For simplicity, compute (rhs mod 2) for all three cases. */ expr_t two, et; two = malloc (sizeof (struct expr)); two -> op = LIT; mpz_init_set_ui (two->operands.val, 2L); makeexp (&et, MOD, e->operands.ops.rhs, two); e->operands.ops.rhs = et; } mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_cmp_si (rhs, 0L) == 0) /* x^0 is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, 0L) == 0) /* 0^y (where y != 0) is 0 */ mpz_set_ui (r, 0L); else if (mpz_cmp_ui (lhs, 1L) == 0) /* 1^y is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, -1L) == 0) /* (-1)^y just depends on whether y is even or odd */ mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); else if (mpz_cmp_si (rhs, 0L) < 0) /* x^(-n) is 0 */ mpz_set_ui (r, 0L); else { unsigned long int cnt; unsigned long int y; /* error if exponent does not fit into an unsigned long int. */ if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) goto pow_err; y = mpz_get_ui (rhs); /* x^y == (x/(2^c))^y * 2^(c*y) */ #if __GNU_MP_VERSION >= 2 cnt = mpz_scan1 (lhs, 0); #else cnt = 0; #endif if (cnt != 0) { if (y * cnt / cnt != y) goto pow_err; mpz_tdiv_q_2exp (lhs, lhs, cnt); mpz_pow_ui (r, lhs, y); mpz_mul_2exp (r, r, y * cnt); } else mpz_pow_ui (r, lhs, y); } mpz_clear (lhs); mpz_clear (rhs); return; pow_err: error = "result of `pow' operator too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); case GCD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_gcd (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case LCM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_lcm (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case AND: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_and (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case IOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_ior (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case XOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_xor (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case NEG: mpz_eval_expr (r, e->operands.ops.lhs); mpz_neg (r, r); return; case NOT: mpz_eval_expr (r, e->operands.ops.lhs); mpz_com (r, r); return; case SQRT: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) < 0) { error = "cannot take square root of negative numbers"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_sqrt (r, lhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case ROOT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (rhs) <= 0) { error = "cannot take non-positive root orders"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) { error = "cannot take even root orders of negative numbers"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } { unsigned long int nth = mpz_get_ui (rhs); if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { /* If we are asked to take an awfully large root order, cheat and ask for the largest order we can pass to mpz_root. This saves some error prone special cases. */ nth = ~(unsigned long int) 0; } mpz_root (r, lhs, nth); } mpz_clear (lhs); mpz_clear (rhs); return; #endif case FAC: mpz_eval_expr (r, e->operands.ops.lhs); if (mpz_size (r) > 1) { error = "result of `!' operator too large"; longjmp (errjmpbuf, 1); } mpz_fac_ui (r, mpz_get_ui (r)); return; #if __GNU_MP_VERSION >= 2 case POPCNT: mpz_eval_expr (r, e->operands.ops.lhs); { long int cnt; cnt = mpz_popcount (r); mpz_set_si (r, cnt); } return; case HAMDIST: { long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); cnt = mpz_hamdist (lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); mpz_set_si (r, cnt); } return; #endif case LOG2: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; if (mpz_sgn (r) <= 0) { error = "logarithm of non-positive number"; longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (r, 2); mpz_set_ui (r, cnt - 1); } return; case LOG: { unsigned long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (lhs) <= 0) { error = "logarithm of non-positive number"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_cmp_ui (rhs, 256) >= 0) { error = "logarithm base too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); mpz_set_ui (r, cnt - 1); mpz_clear (lhs); mpz_clear (rhs); } return; case FERMAT: { unsigned long int t; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); t = (unsigned long int) 1 << mpz_get_ui (lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, t); mpz_add_ui (r, r, 1); mpz_clear (lhs); } return; case MERSENNE: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, mpz_get_ui (lhs)); mpz_sub_ui (r, r, 1); mpz_clear (lhs); return; case FIBONACCI: { mpz_t t; unsigned long int n, i; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "Fibonacci index out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 mpz_fib_ui (r, n); #else mpz_init_set_ui (t, 1); mpz_set_ui (r, 1); if (n <= 2) mpz_set_ui (r, 1); else { for (i = 3; i <= n; i++) { mpz_add (t, t, r); mpz_swap (t, r); } } mpz_clear (t); #endif } return; case RANDOM: { unsigned long int n; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "random number size out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); mpz_urandomb (r, rstate, n); } return; case NEXTPRIME: { mpz_eval_expr (r, e->operands.ops.lhs); mpz_nextprime (r, r); } return; case BINOM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); { unsigned long int k; if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { error = "k too large in (n over k) expression"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } k = mpz_get_ui (rhs); mpz_bin_ui (r, lhs, k); } mpz_clear (lhs); mpz_clear (rhs); return; case TIMING: { int t0; t0 = cputime (); mpz_eval_expr (r, e->operands.ops.lhs); printf ("time: %d\n", cputime () - t0); } return; default: abort (); } }
char * factor (char *str, expr_t *e) { expr_t e1, e2; str = skipspace (str); if (isalpha (str[0])) { int i; int cnt; for (i = 0; fns[i].op != NOP; i++) { if (fns[i].arity == 1) { cnt = matchp (fns[i].spelling, str); if (cnt != 0) { str = expr (str + cnt, &e1); str = skipspace (str); if (str[0] != ')') { error = "expected `)'"; longjmp (errjmpbuf, (int) (long) str); } makeexp (e, fns[i].op, e1, NULL); return str + 1; } } } for (i = 0; fns[i].op != NOP; i++) { if (fns[i].arity != 1) { cnt = matchp (fns[i].spelling, str); if (cnt != 0) { str = expr (str + cnt, &e1); str = skipspace (str); if (str[0] != ',') { error = "expected `,' and another operand"; longjmp (errjmpbuf, (int) (long) str); } str = skipspace (str + 1); str = expr (str, &e2); str = skipspace (str); if (fns[i].arity == 0) { while (str[0] == ',') { makeexp (&e1, fns[i].op, e1, e2); str = skipspace (str + 1); str = expr (str, &e2); str = skipspace (str); } } if (str[0] != ')') { error = "expected `)'"; longjmp (errjmpbuf, (int) (long) str); } makeexp (e, fns[i].op, e1, e2); return str + 1; } } } } if (str[0] == '(') { str = expr (str + 1, e); str = skipspace (str); if (str[0] != ')') { error = "expected `)'"; longjmp (errjmpbuf, (int) (long) str); } str++; } else if (str[0] >= '0' && str[0] <= '9') { expr_t res; char *s, *sc; res = malloc (sizeof (struct expr)); res -> op = LIT; mpz_init (res->operands.val); s = str; while (isalnum (str[0])) str++; sc = malloc (str - s + 1); memcpy (sc, s, str - s); sc[str - s] = 0; mpz_set_str (res->operands.val, sc, 0); *e = res; free (sc); } else { error = "operand expected"; longjmp (errjmpbuf, (int) (long) str); } return str; }
char * term (char *str, expr_t *e) { expr_t e2; str = power (str, e); for (;;) { str = skipspace (str); switch (str[0]) { case 'm': if (match ("mul", str)) { str = power (str + 3, &e2); makeexp (e, MULT, *e, e2); break; } if (match ("mod", str)) { str = power (str + 3, &e2); makeexp (e, MOD, *e, e2); break; } return str; case 'd': if (match ("div", str)) { str = power (str + 3, &e2); makeexp (e, DIV, *e, e2); break; } return str; case 'r': if (match ("rem", str)) { str = power (str + 3, &e2); makeexp (e, REM, *e, e2); break; } return str; case 'i': if (match ("invmod", str)) { str = power (str + 6, &e2); makeexp (e, REM, *e, e2); break; } return str; case 't': if (match ("times", str)) { str = power (str + 5, &e2); makeexp (e, MULT, *e, e2); break; } if (match ("thru", str)) { str = power (str + 4, &e2); makeexp (e, DIV, *e, e2); break; } if (match ("through", str)) { str = power (str + 7, &e2); makeexp (e, DIV, *e, e2); break; } return str; case '*': str = power (str + 1, &e2); makeexp (e, MULT, *e, e2); break; case '/': str = power (str + 1, &e2); makeexp (e, DIV, *e, e2); break; case '%': str = power (str + 1, &e2); makeexp (e, MOD, *e, e2); break; default: return str; } } }
char * expr (char *str, expr_t *e) { expr_t e2; str = skipspace (str); if (str[0] == '+') { str = term (str + 1, e); } else if (str[0] == '-') { str = term (str + 1, e); makeexp (e, NEG, *e, NULL); } else if (str[0] == '~') { str = term (str + 1, e); makeexp (e, NOT, *e, NULL); } else { str = term (str, e); } for (;;) { str = skipspace (str); switch (str[0]) { case 'p': if (match ("plus", str)) { str = term (str + 4, &e2); makeexp (e, PLUS, *e, e2); } else return str; break; case 'm': if (match ("minus", str)) { str = term (str + 5, &e2); makeexp (e, MINUS, *e, e2); } else return str; break; case '+': str = term (str + 1, &e2); makeexp (e, PLUS, *e, e2); break; case '-': str = term (str + 1, &e2); makeexp (e, MINUS, *e, e2); break; default: return str; } } }