Pages

Friday, May 28, 2010

一个烂尾工程:JavaScript 的 BrainFK 解释器

前几天看到Matrix67大牛推荐的名曰Manufactoria的编程游戏,非常之喜欢,玩得快要通关的时候,转念一想,诶,玩这个还不如玩BF呢。

嗯,要么我自己写个类似的BF的网页游戏?

这么一冲动,就刷刷刷写了下面的东西——剩下来的工作主要就是界面了,结果我又发现我没有时间做那工作,还得复习啊。
所以……这个烂尾工程就这么捐出来算了罢,下面的代码属于公有领域

bfcfg = {
    memLen:1024,
    vLimit:0xff
};
 
function BFRunner ( ostream, istream ) {
    this.mem=new Array(bfcfg['memLen']);
    var i;
    for(i=0; i<this.mem.length; ++i)
        this.mem[i]=0;
    this.codepos=0;
    this.mempos=0;
    this.ostream=ostream;
    this.istream=istream;
    return this;
}
 
BFRunner.prototype.compile = function(bfCode) {
    var code=[], n=0, i=0, p=[];
    for(i=0; i<bfCode.length; ++i) {
        if(bfCode[i].match(/[+-<>,.]/)) {
            code.push(bfCode[i]);
            ++n;
        } else if(bfCode[i]=='[') {
            p.push(code.length);
            code.push('!');
        } else if(bfCode[i]==']') {
            if(p.length<1) {
                throw "too many ']'s";
            }
            var jumpPoint=p.pop()
            code[jumpPoint]=code.length;
            code.push(-jumpPoint);
        }
    }
    if(p.length!=0) {
        throw "too many '['s";
    }
    this.code = code;
    return this;
}
 
BFRunner.prototype.reset = function() {
    var i;
    for(i=0; i<this.mem.length; ++i)
        this.mem[i]=0;
    this.codepos=0;
    this.mempos=0;
    return this;
}
 
BFRunner.prototype.step = function() {
    if(this.codepos<this.code.length) {
        if( this.code[this.codepos] == '+' ) {
            if(++(this.mem[this.mempos])>bfcfg['vLimit'])
                this.mem[this.mempos]=0;
        } else if( this.code[this.codepos] == '-' ) {
            if(--(this.mem[this.mempos])<0)
                this.mem[this.mempos]=bfcfg['vLimit'];
        } else if( this.code[this.codepos] == '<' ) {
            --this.mempos;
            if(this.mempos<0)
                this.mempos=bfcfg['memLen']-1;
        } else if( this.code[this.codepos] == '>' ) {
            ++this.mempos;
            if(this.mempos>=bfcfg['memLen'])
                this.mempos=0;
        } else if( this.code[this.codepos] == ',' ) {
            this.mem[this.mempos] = this.istream.get();
        } else if( this.code[this.codepos] == '.' ) {
            this.ostream.put(this.mem[this.mempos]);
        } else if( typeof(this.code[this.codepos]) == 'number' ) {
            var pos=Number(this.code[this.codepos]);
            if ( pos>0 && !this.mem[this.mempos] )
                this.codepos = pos;
            else if( pos<=0 )
                this.codepos = -pos-1;
        } else {
            throw("WTF!!");
        }
        ++this.codepos;
        return this;
    } else {
        return undefined;
    }
}
 
BFRunner.prototype.run = function() {
    var p=0, i=0;
    for(i=0; i<this.mem.length; ++i)
        this.mem[i]=0;
    i=0;
    while(i<this.code.length) {
        if( this.code[i] == '+' ) {
            if(++this.mem[p]>bfcfg['vLimit'])
                this.mem[p]=0;
        } else if( this.code[i] == '-' ) {
            if(--this.mem[p]<0)
                this.mem[p]=bfcfg['vLimit'];
        } else if( this.code[i] == '<' ) {
            --p;
            if(p<0)
                p=bfcfg['memLen']-1;
        } else if( this.code[i] == '>' ) {
            ++p;
            if(p>=bfcfg['memLen'])
                p=0;
        } else if( this.code[i] == ',' ) {
            this.mem[p] = this.istream.get();
        } else if( this.code[i] == '.' ) {
            this.ostream.put(this.mem[p]);
        } else if( typeof(this.code[i]) == 'number' ) {
            var pos=Number(this.code[i]);
            if ( pos>0 && this.mem[p]===0 )
                i = pos;
            else if( pos<=0 )
                i = -pos-1;
        }
        ++i;
    }
    return this;
}
 
function ISStream(str) {
    this.arr=new Array(str.length);
    this.pos=0;
    for(var i=0; i<str.length; ++i){
        this.arr[i] = str.charCodeAt(i);
    }
    return this;
}
 
ISStream.prototype.set = function(str) {
    this.arr=new Array(str.length);
    this.pos=0;
    for(var i=0; i<str.length; ++i){
        this.arr[i] = str.charCodeAt(i);
    }
    return this;
}
 
ISStream.prototype.get = function() {
    if(this.pos>=this.arr.length) {
        return 0;
    } else {
        return this.arr[this.pos++];
    }
}
 
ISStream.prototype.reset = function() {
    this.pos = 0;
    return this;
}
 
function OSStream() {
    this.arr=[];
}
 
OSStream.prototype.reset = function() {
    this.arr=[];
}
 
OSStream.prototype.put = function(ch) {
    this.arr.push(String.fromCharCode(ch));
}
 
OSStream.prototype.str = function() {
    return this.arr.join("");
}


Try it out:

99 Bottles of Beer in Urban Mueller's BrainF*** (The actual
name is impolite)

by Ben Olmstead

ANSI C interpreter available on the internet; due to
constraints in comments the address below needs to have the
stuff in parenthesis replaced with the appropriate symbol:

http://www(dot)cats(dash)eye(dot)com/cet/soft/lang/bf/

Believe it or not this language is indeed Turing complete!
Combines the speed of BASIC with the ease of INTERCAL and
the readability of an IOCCC entry!

>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]

No comments:

Post a Comment