Hello!
Today I was playing with the game configuration/console, I've got most of the reference for the syntax and command from "
Console Tips & Tricks".
Does the language used by the configuration have a name? Is there some actual documentation for it?
I've noticed that variables act weirdly inside aliases, it appears that they are not updated as soon as a new value is assigned to them.
The following code demonstrates that:
Code:
alias test1 "set param $1; echo $1 - $param;";
Calling
test1 with some parameter will reveal that
$param keeps old values, while
$1 is correct.
I've found that this can be solved in the following way:
Code:
alias test2a "echo $1 - $param;";
alias test2 "set param $1; test2a $1";
It seems weird enough to me.
I'm new to this so maybe I'm not using
set properly, is there some other way to have (local) variables?
Hi! Thanks for your interest in the Xonotic console, I think it's wonderful to play with.
First of all, there is no name for the language. It's very generic and doesn't have a lot of features in itself.
The behavior you describe is nothing surprising once you know how the variable expansion is done: the variables are expanded for the entire compound command (i.e. for all the commands separated by semicolons) before it is interpreted. If we imagine that we set $param to "bar" before calling your alias as "test1 foo", the resulting command is
Code:
set param foo; echo foo - bar;
The workaround you suggest is the proper way to get the behaviour you want: $param is expanded in test2a only after it is set by test2.
Thanks for the info.
I've been able to recreate some higher level control structure so I guess it's Turing complete at least.
I have a few more questions though.
Is it possible to make a defition of an alias spread across multiple lines?
Something like the following does not seem to work:
Code:
alias foo "echo hello;
echo world"
Is it possible to defer variable expansion?
I've implemented a
for loop and I'd like more to be able to use
rather than
Code:
alias for_body echo $i
for i 0 10 for_body
It is Turing complete indeed!
You can defer variable expansion, yes. You just need to escape the $ by doubling it.
Here's a subtle detail you should note to help you make sense out of this all: "alias" lines receive a special treatment. When a command starts (excepting whitespace) with alias, no variable expansion is done on the arguments. That is why you can simply do
and $bar will only be expanded when calling foo. That's a behavior specific to alias. To circumvent that and make expansion work the same as in other commands, you can put alias between quotes:
Code:
"alias" foo echo $bar
and the alias will include the value of the referenced variable
at definition time.
That means the following two commands are equivalent:
Code:
alias foo echo $bar
"alias" foo echo $$bar
EDIT: I'll also mention Blub's contribution to console scripting from a few years ago (2008!). He basically implemented an instruction set based on x86! He then implemented a few constructs such as a for loop using that new language. You can find the old thread here:
http://www.alienTRAP.org/archive/forum/v...php?t=2875
Thanks again!
Playing with the console is kinda fun.
I hope now that I'll keep playing with the shooter as well
One last question: is it possible to extract a character from a string? (By random access, trimming the string or with some other method)
That's not possible, unfortunately.
You can extract only substrings from the beginning of a string, but not in the middle. This is done using the one-string sprintf from the set of rpn commands, and taking advantage of the precision for string specifiers. Example:
Code:
menu_cmd rpn /abcdefg /%.3s sprintf1s
leaves "abc" on the stack. To store the three first characters of $foo into $result, this becomes
Code:
set foo abcdefg
menu_cmd rpn /result /foo load /%.3s sprintf1s def
I've kept playing with this and found a way to get a specific character from a string.
After tons of alias hacks now I have a colorful chat, kida like Mario.
Really? Can you share it?
Haha wow, heavy stuff! I'd need some time to read through that. I thought about bruteforcing like you do to get the character, but I thought it would not be worth the effort to implement it. But I still love that you did it.
As for string comparison, there are two implementations of it in blub's vmutil.cfg. Say you have two strings, $1 and $2. The first way is to define alias strcmp_$1 to set a result variable to false, and strcmp_$2 to set that variable to true. Then, you call strcmp_$1. If the strings are the same, the result will be true. You can use unalias to avoid polluting the namespace.
The second way is to take advantage of the toggle command with arguments. Modifying the original implementation a bit to cut the x86 stuff:
Code:
alias strcmp "set result \"_$1\"; toggle result 0 \"_$2\" 1"
If $1 is equal to $2, toggle will cycle the value of result to 1. If not, it will use the first value of the 0, _$2, 1 cycle which is 0. The underscore is to avoid the case where $1 or $2 are "0" or "1".
That's interesting, is there anywhere some exaustive reference for all the built-in commands? help is not really helpful...
I've never seen a scripting language that's so low level, lower level than x86 assembly as it seems. It's kinda fun to write stuff in it though.
Unfortunately I don't think there's a reference for those. You can use "cmdlist" but that will give you a ton of useless commands in the bunch. "apropos" is an interesting one when it comes to help: it searches in descriptions of commands and variables.
Congratulations! You just passed the test for the
divVerent Certified Xonotic Console Expert (DCXCE)
Your badge will soon be provided.
Ha, silly me. I was calculating all the
n characters when calling
mb_string_ch n "foo".
Now it's much better. I've also fixed the space bug.
mb_string_ch:
Code:
alias mb_string_ch_set_result_if_body "set mb_string_ch_result \"${$mb_string_ch_nextchar}\"; set mb_for_counter 999"
alias mb_string_ch_set_result "mb_if $mb_streq_result mb_string_ch_set_result_if_body"
alias mb_string_ch_check " mb_streq \"$mb_string_ch_match_1\" \"$mb_string_ch_match_2\"; mb_string_ch_set_result"
alias mb_string_ch_check_set "set mb_string_ch_match_1 \"$mb_string_ch_firstchar${$mb_string_ch_nextchar}\"; rpn /mb_string_ch_match_2 /mb_string_ch_str load /%.${mb_string_ch_index}s sprintf1s =; mb_string_ch_check"
alias mb_string_ch_loop_body "set mb_string_ch_nextchar mb_ascii_opt_$mb_string_ch_i; mb_string_ch_check_set"
alias mb_string_ch_loop "mb_for mb_string_ch_i 0 93 mb_string_ch_loop_body"
alias mb_string_ch_set_first "rpn /mb_string_ch_firstchar /mb_string_ch_str load /%.${mb_string_ch_index}s sprintf1s = /mb_string_ch_index dup load 1 + =; mb_string_ch_loop; "
alias mb_string_ch_check_0_if_exit rpn /mb_string_ch_result /mb_string_ch_str load /%.1s sprintf1s =
alias mb_string_ch_check_0_if "mb_if_else $mb_if_condition mb_string_ch_check_0_if_exit mb_string_ch_set_first"
alias mb_string_ch_check_0 "rpn /mb_if_condition /mb_string_ch_index load 0 < =; mb_string_ch_check_0_if"
alias mb_string_ch "set mb_string_ch_str ${2- asis}; rpn /mb_string_ch_index $1 =; mb_string_ch_check_0"
mb_print:
Code:
alias mb_print_say "say $mb_print_result"
alias mb_print_echo "echo $mb_print_result"
alias mb_print_loop_add_character "set mb_print_result \"$mb_print_result$mb_print_hue_str$mb_string_ch_result\""
alias mb_print_loop_body_2 "mb_hue $mb_print_hue mb_print_hue_str; mb_print_loop_add_character; rpn /mb_print_hue dup load /mb_print_hue_step load + ="
alias mb_print_loop_body_1 "mb_string_ch $mb_print_i \"$mb_print_str\""
alias mb_print_loop_body "mb_print_loop_body_1; mb_print_loop_body_2"
alias mb_print_loop "mb_forX mb_print_i 0 $mb_print_sl mb_print_loop_body"
alias mb_print_counter_set "rpn /mb_print_sl /mb_strlen_count load 1 - =; rpn /mb_print_hue 0 =; rpn /mb_print_hue_step 360 /mb_strlen_count load / floor ="
alias mb_print_strlen "mb_strlen \"$mb_print_str\""
alias mb_print_setup "set mb_print_result ^xf00; set mb_print_str ${*}; mb_print_strlen; mb_print_counter_set; mb_print_loop;"
alias mb_print "mb_print_setup ${*}; mb_print_echo; mb_print_say"
alias mb_echo "mb_print_setup ${*}; mb_print_echo"
alias mb_say "mb_print_setup ${*}; mb_print_say"
Scripting the Xonotic console has enough complexity and fun that I've set up a
git repo for this.
A couple of other players are using my script for colored chat. I'll start a thread focused on that.