Computer Science Canada

Turing RealTime Net

Author:  Saad [ Sun Jun 24, 2007 6:59 pm ]
Post subject:  Turing RealTime Net

Real Time Internet



Requirements:
• Knowledge of Net Commands
• String Manipulation Skills

Turing’s Net Drawbacks:

If you start playing around with Turing’s Net Features, you will realize that you can send one data over the net to another person really fast, but if you tried sending more then 1 variable, it would not work properly.


So what to do to fix it?

Since one variable can be sent through the Net module safely, we need to find a way to combine all the information we want to send over the net. One method would be to use tokenized strings. A tokenized string is a string that is part of a bigger string, separated by delimiters.

To put all the data into one string should not be hard as you can easily convert to string and add the delimiter after. I.e.
var c := intstr (px) + "/" + intstr (py)

If the Player X and Player Y variables both had the value 250, our string would be “250/250”. We will send this over the net to the receiver. This saves us from sending two variables: Player X and then Player Y.

Now we have a new problem: how do we read this information? I have made a sample Get_Token function to assist us.


Turing:

body fcn Get_Token
    var tmsg := msg
    var toks : flexible array 1 .. 1 of string
    var b := 1
    if index (tmsg, del) = 0 then
/* Checks if the delimeter is inside the string and if its not it will either result the message or if the token requested is > 1 then it will return null */
        if num > 1 then
            result "null"
        else
            result tmsg
        end if
    else
/* If its in the string then it will do the process of splitting the string apart into tokens*/
        loop
            toks (b) := tmsg (1 .. index (tmsg, del) - 1)
            tmsg := tmsg (index (tmsg, del) + 1 .. *)
            exit when index (tmsg, del) = 0
            b += 1
            new toks, upper (toks) + 1
        end loop
        b += 1
        new toks, upper (toks) + 1
        toks (b) := tmsg
    end if
    new toks, upper (toks) + 1
/* If the token requested is greater then the number of tokens it retruns null */
    if num > b then
        result "null"
    else
        result toks (num)
    end if
end Get_Token


After we have sent the “250/250” string to our receiver, the receiver needs to read the tokens.
Token #1 results the X location and Token #2 results the Y location. This saves us from getting 2 variables from the net stream.

A slight drawback to this method is that Turing’s string's can be a maximum of 255 characters long, so you will have to be creative when sending the data. For example instead of base ten numbers like 15 you could send its hexadecimal value “F”. I will not get into detail here since that would require another tutorial.

I have attached a simple ball movement program in real time with two people.
Yes I could have used records but for simplicity I did not.


Example
Turing:
forward fcn Get_Token (msg : string, num : int, del : char) : string
/* Real Time Internet by Saad Ahmad */
/* Limits are 255 string limit */
var choice : int
loop
    cls
    put "1 -> Host"
    put "2 -> Join"
    get choice
    exit when choice > 0 and choice < 3
end loop
var stream : int
var address : string
const port := 5055
var px, py := 250
var msg := "250/250"   /* Default Location for players */
var key : array char of boolean
var p2x, p2y := 100
if choice = 1 then
    put "Your ip is ", Net.LocalAddress
    stream := Net.WaitForConnection (port, address)
    View.Set ("offscreenonly")
    loop
        var b := msg
        if Net.TokenAvailable (stream) then  /* Checks if string is available */
            get : stream, b : *
        end if
        Input.KeyDown (key)
        if key (KEY_UP_ARROW) then
            py += 10
        end if
        if key (KEY_DOWN_ARROW) then
            py -= 10
        end if
        if key (KEY_LEFT_ARROW) then
            px -= 10
        end if
        if key (KEY_RIGHT_ARROW) then
            px += 10
        end if
        p2x := strint (Get_Token (b, 1, "/")) /* Gets the location X which we made token #1 */
        p2y := strint (Get_Token (b, 2, "/")) /* Gets the location Y which we made token #2 */
        msg := b

        Draw.FillOval (px, py, 10, 10, red)
        var c := intstr (px) + "/" + intstr (py) /* Makes information one string and sends it */
        put : stream, c
        Draw.FillOval (p2x, p2y, 10, 10, yellow)
        View.Update
        Time.DelaySinceLast (50)
        cls
    end loop
end if
if choice = 2 then
    var a : string
    put "Enter IP"
    get a
    stream := Net.OpenConnection (a, port)
    View.Set ("offscreenonly")
    if stream > 0 then
        loop
            var b := msg
            if Net.TokenAvailable (stream) then /* Checks if string is available */
                get : stream, b : *
            end if
            msg := b
            Input.KeyDown (key)
            if key (KEY_UP_ARROW) then
                py += 10
            end if
            if key (KEY_DOWN_ARROW) then
                py -= 10
            end if
            if key (KEY_LEFT_ARROW) then
                px -= 10
            end if
            if key (KEY_RIGHT_ARROW) then
                px += 10
            end if
            p2x := strint (Get_Token (b, 1, "/"))  /* Gets the location X which we made token #1 */
            p2y := strint (Get_Token (b, 2, "/")) /* Gets the location Y which we made token #2 */
            msg := b

            Draw.FillOval (px, py, 10, 10, red)
            var c := intstr (px) + "/" + intstr (py) /* Makes information one string and sends it */
            put : stream, c
            Draw.FillOval (p2x, p2y, 10, 10, yellow)
            View.Update
            Time.DelaySinceLast (50)
            cls
        end loop
    end if
end if


/* Main body of Get_Token
 Tokens are just words in a string which are seperated by a delimeter
 */


body fcn Get_Token
    var tmsg := msg
    var toks : flexible array 1 .. 1 of string
    var b := 1
    if index (tmsg, del) = 0 then
        /* Checks if the delimeter is inside the string and if its not
         it will either result the message or if the token requested is > 1
         then it will return null */

        if num > 1 then
            result "null"
        else
            result tmsg
        end if
    else
        /* If its in the string then it will do the process of splitting
         the string apart into tokens*/

        loop
            toks (b) := tmsg (1 .. index (tmsg, del) - 1)
            tmsg := tmsg (index (tmsg, del) + 1 .. *)
            exit when index (tmsg, del) = 0
            b += 1
            new toks, upper (toks) + 1
        end loop
        b += 1
        new toks, upper (toks) + 1
        toks (b) := tmsg
    end if
    new toks, upper (toks) + 1
    /* If the token requested is greater then the number of tokens it retruns null */
    if num > b then
        result "null"
    else
        result toks (num)
    end if
end Get_Token



At the end I would like to say this is a very effective method of achieving RealTime Net. Using records over the net stream will not work and also for me, putting lots of variables in the net stream wont work properly which I think is true for other people aswell.

I hope you liked this. Smile

Also thanks Cervantes for checking over this tutorial Claping


Saad

Author:  LaZ3R [ Sun Jun 24, 2007 7:27 pm ]
Post subject:  RE:Turing RealTime Net

Nice tutorial indeed, it's pretty much the same thing I did when making my first few online games in turing Smile, very effective way of doing it.

Author:  Cervantes [ Sun Jun 24, 2007 9:21 pm ]
Post subject:  RE:Turing RealTime Net

Thanks!
+100 bits, and karma.

Author:  Decadence666 [ Sun Jun 24, 2007 9:49 pm ]
Post subject:  RE:Turing RealTime Net

Psycho. Very useful. What I need now is a way to run two turing windows at the same time Wink

Author:  CodeMonkey2000 [ Sun Jun 24, 2007 9:54 pm ]
Post subject:  RE:Turing RealTime Net

What does the keyword forward do? Is that like a function prototype?

Author:  Saad [ Sun Jun 24, 2007 10:07 pm ]
Post subject:  Re: Turing RealTime Net

Pretty much, with forward you can declare the header of the function. This is usefull when you 2 procedures need to call on each other and also you can put all you functions at the end.

Author:  Wolf_Destiny [ Wed Jun 27, 2007 7:32 pm ]
Post subject:  Re: Re: Turing RealTime Net

Decadence666 @ Sun Jun 24, 2007 9:49 pm wrote:
Psycho. Very useful. What I need now is a way to run two turing windows at the same time Wink

That's easy, compile one of the two programs, then run the compiled program, and the uncompiled from Turing. (Or compile both, but that'd take a couple minutes more)
~Wolf_Destiny
P.S. Also if you just want to run two of the same program, once it's compiled you should be able to run as many of it as you want. But Turing is also a CPU hog, so more then two would probably be a bad thing.


: