Jump to content
BrainDen.com - Brain Teasers
  • 0


unreality
 Share

Question

VNA

VNA stands for Virtual Node Array, and is the setting for this game, which I based loosely off of Core Wars, an old programming game... but Redcode was pretty hard to understand IMO, I think VNA Code (which I have invented over the past two days) is better and easier to learn. You need no knowledge of Redcode or Core Wars to play this game.

Back to the game.

The VNA is like a computer memory space, one-dimensional, and filled with nodes. A node is like a line of programming code. Before the game begins, all of the VNA's nodes have the BLANK command, but when the game begins, two programs are put into the VNA at random locations. The programs designed by YOU, the players of the game! They retain their order and everything, they're just placed in at a random spot in the VNA, though considerably far away from each other.

Each node refers to itself as 0, while the next line is 1 and the previous line is -1. The VNA wraps around so it's like a loop of nodes.

So in the beginning of the game, both player's programs are put into the VNA, and then each player starts with one 'executor'. An executor starts at the beginning line of the player's program and then executes that node, then the next, etc.

In one round, Player 1 (P1)'s executor executes one node, and P2's executor does the same. Then in the next round, etc.

Using the SPLIT and MERGE commands, new executors can be made or deleted. Let's say P1 has 2 executors while P2 has 1. The game would proceed like this:

Round One

* P1's first executor

* P2's executor

Round Two

* P1's second executor

* P2's executor

etc. Each player can have up to four executors running at any one time.

The goal of the game is to destroy the opponent's executors and be the sole master of the Virtual Node Array! Note that once your initial executor starts running, you have no more impact in the game except to see the outcome.

So how to program in VNA Code?

First, the commands. Each node is essentially a command. Each command (except BLANK) is followed by three values: a,b,c. If not specified, they are assumed to be zero. I call the a/b/c values input vectors, and they can be either a number or a function (will get to functions next).

The commands:


COPY a,b	   copies line a into line b (overriding the current line b)

JUMP a		 jumps execution to line a

BOMB		   destroys the executor that executed this node

SPLIT a		creates a new executor which begins running at line a. Cannot create more than four

MERGE		  deletes the most recently created executor. Cannot delete the initial executor

EDITA a,b	  a is the line number, b is the new a value for that node

EDITB a,b	  a is the line nummber, b is the new b value for that node

EDITC a,b	  a is the line number, b is the new c value for that node

BLANK		  what the original VNA is filled with. You can use BLANK commands too, it's basically a "do-nothing" command. BLANKs cannot hold a/b/c values like other commands can


Note that there are no 'c' fields in usage, but I left the possibility open for both data storage and in case I add more commands later that need a third input value as well


So, a/b/c values are either numbers (usually line numbers, remember that each node refers to itself as line 0) OR functions. So what are functions?


The functions:


a(n)			returns the a value of the node at line n

b(n)			returns the b value of the node at line n

c(n)			returns the c value of the node at line n

add(m,n)		returns m+n

sub(m,n)		returns m-n

mul(m,n)		returns m*n

div(m,n)		returns m/n

mod(m,n)		returns the remainder of m/n

pow(m,n)		returns m^n

com(m,n,o,p,q)  compares m & n. If they are equal, returns o. If m>n, returns p. If n>m, returns q

exe()		   returns the number of executors that you have currently running

num()		   returns the number of lines in the VNA

That's all I've got right now, but I think it's enough. You can nest functions within functions, in case you were wondering - in fact I do that in my example program. I call it 'The Bomber'

COPY 3, 4

EDITB -1, add(b(-1), 1)

JUMP -2

BOMB

Whoa! What's that do? The COPY command copies line 3 (which would be the BOMB) into line 4 (just a BLANK before, now it's a BOMB too). So this part of the VNA looks like this now:

COPY 3, 4

EDITB -1, add(b(-1), 1)

JUMP -2

BOMB

BOMB

In the next round, the next line is executed. The command on this node is EDITB, which edits the b field of a certain line. That line is in EDITB's a field, which is -1, so it's editing the b field of the line right before it. The line is edited to adding the CURRENT b field value [b(-1)] with the number 1. Basically, this EDITB line is incrementing the COPY's b field by 1. So the new code looks like this:

COPY 3, 5

EDITB -1, add(b(-1), 1)

JUMP -2

BOMB

BOMB

The next line is JUMP -2, which sends the executor backwards 2 lines to the COPY node again - phew that was close, we almost hit the BOMB command!

So now the program runs all over again, except this time it copies the BOMB command to line 5 (the next BLANK). Thus, as the executor loops over these three lines, it spews out a chain of BOMBs to eventually march upon the opponent. That's why I call it the Bomber :D

This isn't the perfect Bomber - because it only spews a BOMB command every third round, and the BOMB only advances one node each time. Depending on the size of the VNA, the opponent could have destroyed you by the time you lay the tenth BOMB. One way is to, based on the number of lines in the VNA, skip a certain amount of lines to place the next BOMB.

I made this slightly more complicated program next, I call it the Bomb Evader:

SPLIT -3

JUMP com(exe(),1,4,1,1)

MERGE

EDITA -3, sub(a(-3),2)

JUMP -4

COPY 2, sub(a(-5),7)

JUMP sub(a(-5),8)

JUMP 0

It works by sending a secondary executor backwards toward the opponent, with the initial executor checking to see if it's still alive with exe(). When/if the secondary executor is killed, the executor copies the line 'JUMP 0' to that line and then jumps itself to the JUMP 0 line, thus staying in the same place while the opponent's BOMBs continue past, destroying the original program, looping back around, and killing the Bomber, while the Bomb Evader stays alive. This could fail, however, if the Bomber is, say, 4 lines long and did some math to make a BOMB every 5th line done so that if it looped back around (based on num()) it would avoid itself. Though it would also be unlikely to hit the JUMP 0

If you're interested in building your own battle program and warring with other people, post here :D The cool thing is that I can play too ;D

Link to comment
Share on other sites

  • Answers 197
  • Created
  • Last Reply

Top Posters For This Question

Recommended Posts

  • 0

It's harder than I anticipated to make the emulator. Everything is great as of now - all of the commands except EDIT are working perfectly. The complicated workings of SPLIT, MERGE and BOMB and everything else dealing with executors, executor order, etc, are working perfectly fine, as are all other commands except...

*drumroll*

You guessed it, EDITA/EDITB/EDITC. While starting to code for EDITA (I just got around to it), I realized a flaw in something earlier I had done - the code for separating the line after the space after the command into the three input vectors (a/b/c)... I used commas to determine the iv's apart, and it's been working ONLY because I've only used numbers so far, since I haven't made the function evaluator yet. I forgot that functions with more than one input value use commas to distinguish

So I'm proposing a change which will affect all VNA code:

semicolons between function input values

I was originally considering semicolons instead of commas for the a/b/c values, but those are used much more prominently (and on every line) than those functions with multiple input. Also having separate punctuations (semicolons and commas) will help make the code easier to read

so something like this:

COPY c(3), add(b(1), mul(7, a(1))), com(b(2),b(3),1,5,7)

would become:

COPY c(3), add(b(1); mul(7; a(1))), com(b(2); b(3); 1; 5; 7)

that is, all commas within functions become semicolons

Sorry about the limited string-manipulation capabilities of HyperCard, it's my only medium for programming right now :D Is everyone okay with this switch?

edit: if it would be easier to look at, we could make it so that all input values of a function are followed by a semicolon, but only optional for functions with one input value. So that same line would look like this:

COPY c(3), add(b(1); mul(7; a(1););), com(b(2); b(3); 1; 5; 7;)
Though the optional thing may be hard, it would probably have to be after every input value, including the single-input functions:
COPY c(3;), add(b(1;); mul(7; a(1;););), com(b(2;); b(3;); 1; 5; 7;)

Or it could be a symbol other than semicolon. Whatever you guys want

Edited by unreality
Link to comment
Share on other sites

  • 0
It's harder than I anticipated to make the emulator. Everything is great as of now - all of the commands except EDIT are working perfectly. The complicated workings of SPLIT, MERGE and BOMB and everything else dealing with executors, executor order, etc, are working perfectly fine, as are all other commands except...

*drumroll*

You guessed it, EDITA/EDITB/EDITC. While starting to code for EDITA (I just got around to it), I realized a flaw in something earlier I had done - the code for separating the line after the space after the command into the three input vectors (a/b/c)... I used commas to determine the iv's apart, and it's been working ONLY because I've only used numbers so far, since I haven't made the function evaluator yet. I forgot that functions with more than one input value use commas to distinguish

So I'm proposing a change which will affect all VNA code:

semicolons between function input values

I was originally considering semicolons instead of commas for the a/b/c values, but those are used much more prominently (and on every line) than those functions with multiple input. Also having separate punctuations (semicolons and commas) will help make the code easier to read

so something like this:

COPY c(3), add(b(1), mul(7, a(1))), com(b(2),b(3),1,5,7)

would become:

COPY c(3), add(b(1); mul(7; a(1))), com(b(2); b(3); 1; 5; 7)

that is, all commas within functions become semicolons

Sorry about the limited string-manipulation capabilities of HyperCard, it's my only medium for programming right now :D Is everyone okay with this switch?

edit: if it would be easier to look at, we could make it so that all input values of a function are followed by a semicolon, but only optional for functions with one input value. So that same line would look like this:

COPY c(3), add(b(1); mul(7; a(1););), com(b(2); b(3); 1; 5; 7;)
Though the optional thing may be hard, it would probably have to be after every input value, including the single-input functions:
COPY c(3;), add(b(1;); mul(7; a(1;););), com(b(2;); b(3;); 1; 5; 7;)

Or it could be a symbol other than semicolon. Whatever you guys want

If you have a new seperator ( I will have to adjust my emulator) I would suggest semicolums between a/b/c and commas in parameters. It well look a lot tidy that way..

I will send you my PHP script Unreality when I am finished so you can read over the code :D Maybe learn to trust it.

We should test out emulators with eachother to test to see if they output the same :D

Link to comment
Share on other sites

  • 0
so like this:

COPY a; b; c;

or none after the c?

COPY a; b; c

COPY add(c(2),mul(a(1),3)); c(3); 7

yeah I guess that looks good :P So the new VNA format is semicolons between command input vectors?

It just means that I have to go back and change my program! :( Its almost done.. :D

Link to comment
Share on other sites

  • 0
It just means that I have to go back and change my program! :( Its almost done.. :D

I just played through the battle we had before with my emulator. You won :( I ran into the bomb your dropped at the start :( 50% of the time that would happen..

I think I have finished my emulator.. :D Though You could probably put it in an infinite loop :( and can assign a/b/c varibles to blank lines :(

Link to comment
Share on other sites

  • 0
I just played through the battle we had before with my emulator. You won :( I ran into the bomb your dropped at the start :( 50% of the time that would happen..

I think I have finished my emulator.. :D Though You could probably put it in an infinite loop :( and can assign a/b/c varibles to blank lines :(

Should be working now ;D

http://taliesin.net78.net/Brainden/VNA/

Link to comment
Share on other sites

  • 0

I don't think it's working - something's messy with the functions. The add doesn't exist, and it replaced some stuff with numbers, ie, simplifying some functions into numbers I think, but that can't happen with the VNA (it could happen behind-the-scenes of course, but it can't edit the actual line and remove funcs unless an EDIT command has been used)

Another thing that confuses me is the executors. Where are they, how I can tell what is running what, etc?

But so far it looks good :D I'll go work on mine

Link to comment
Share on other sites

  • 0
I don't think it's working - something's messy with the functions. The add doesn't exist, and it replaced some stuff with numbers, ie, simplifying some functions into numbers I think, but that can't happen with the VNA (it could happen behind-the-scenes of course, but it can't edit the actual line and remove funcs unless an EDIT command has been used)

Another thing that confuses me is the executors. Where are they, how I can tell what is running what, etc?

But so far it looks good :D I'll go work on mine

Can you post the code which causes this to happen?

Player 1 program: Light Blue

Player 2 program: Light Greed

Player 1 executor: Dark Blue

Player 2 executor: Dark Green

There is also a Link at the top P1E1 ( wich will just to Player 1 first executor) and P2E1

Link to comment
Share on other sites

  • 0

player1/player2 program actually doesn't matter, since that only matters in the original placement, what matters after that is executors :D But cool! Oh btw, for my emulator at least, I made exe() have an input:

exe(1) - returns the number of P1's executors

exe(2) - returns the number of P2's executors

I only did that because the function evaluator doesn't know which player is doing the function, but it is a good concept :P If we want to keep that not part of the game I can just edit people's exe() functions (if they use them) to be exe(1) or exe(2) depending on their player number, so you don't have to adjust your code if you don't want to

Aaanyway, good news! My emulator is complete! It works great, though I'm not sure how many nested functions it can do before it bursts lol, it's an older computer :P

Mekal PM me (or post) your 'Tidal Wave' program

Link to comment
Share on other sites

  • 0

Wow I just made two programs (based on my memory of earlier ideas, I didn't have my handy VNA text file cuz it was on the other comp) and pitted them against each other:

The Hopper

copy 0;80;0

edita -1;add(a(-1),1);0

editb -2;add(b(-2),1);0

jump com(a(-3),5,77,77,-3);0;0

The Bomber

jump 2;0;0

bomb 0;0;0

copy -1;30;0

editb -1;add(b(-1),4);0

jump -2;0;0

The random generator gave line 96 as the Bomber's starting line, I left that and then began the simulation - I have a button that does a single round, so I pressed it a bunch of times, watching the action unfold

and man it was awesome! :P It was seriously nailbiting. The Hopper hopped around, a few times being narrowly missed by the Bomber's bombs. The Hopper was around 40 or 80 or something when the Bomber replaced the last, and newly copied, line of the Hopper's code with a Bomb, but also the Bomber was a few rounds away from bombing itself to shreds! (It was a simple program, and I didn't program in any sort of defense mechanism like my Shielded Phoenix has to stop it from bombing itself). It came down to the hair-raising finale and the Hopper hit a bomb first before the Bomber bombed itself, and Program 2 won

whoo that was awesome :P

Link to comment
Share on other sites

  • 0

here's Mekal's Tidal Wave:

Copy 5, -1

Copy 4, 5

EDITB -2, add(b( -2 ),-1)

EDITB -2, add(b( -2), 1)

JUMP -4

BOMB

in the syntax my emulator understands: (caps or lower case doesn't matter)

copy 5;-1;0

copy 4;5;0

editb -2;add(b(-2),-1);0

editb -2;add(b(-2),1);0

jump -4;0;0

bomb 0;0;0

great program Mekal! When I get on the other comp I'll be able to get my program and then we can fight :P

Link to comment
Share on other sites

  • 0
Wow I just made two programs (based on my memory of earlier ideas, I didn't have my handy VNA text file cuz it was on the other comp) and pitted them against each other:

The Hopper

copy 0;80;0

edita -1;add(a(-1),1);0

editb -2;add(b(-2),1);0

jump com(a(-3),5,77,77,-3);0;0

The Bomber

jump 2;0;0

bomb 0;0;0

copy -1;30;0

editb -1;add(b(-1),4);0

jump -2;0;0

The random generator gave line 96 as the Bomber's starting line, I left that and then began the simulation - I have a button that does a single round, so I pressed it a bunch of times, watching the action unfold

and man it was awesome! :P It was seriously nailbiting. The Hopper hopped around, a few times being narrowly missed by the Bomber's bombs. The Hopper was around 40 or 80 or something when the Bomber replaced the last, and newly copied, line of the Hopper's code with a Bomb, but also the Bomber was a few rounds away from bombing itself to shreds! (It was a simple program, and I didn't program in any sort of defense mechanism like my Shielded Phoenix has to stop it from bombing itself). It came down to the hair-raising finale and the Hopper hit a bomb first before the Bomber bombed itself, and Program 2 won

whoo that was awesome :P

Did you get the same outcome with my sim?

Link to comment
Share on other sites

  • 0

I didn't try your emulator, you can if you want, but if the outcome is different than something is wrong with yours, not mine :D I didn't mean that to sound cocky either, just that I tested, re-tested, checked and re-checked mine and it fits perfectly with how the VNA is supposed to work, down to the detail. So you should check and see if you get the same result ;D

actually one difference is that when I say line 96, that's if you're starting at 1 and going to 200. If yours starts at 0 and goes to 199, then the Bomber started at 95

Oh and I managed to extract my program from my other computer, it was basically Shielded Phoenix with some minor differences.

So I ran the fight in the emulator.

Tidal Wave

copy 5;-1;0

copy 4;5;0

editb -2;add(b(-2),-1);0

editb -2;add(b(-2),1);0

jump -4;0;0

bomb 0;0;0

Shielded Phoenix

JUMP 2;0;0

BOMB 27;0;0

JUMP com(com(a(a(-1)),b(a(-1)),a(a(-1)),1,1),0,1,3,3);0;0

EDITA -2;add(a(-2),3);0

JUMP com(a(-3),168,4,4,-2);3;0

COPY -4;sub(a(-4),b(-1));0

EDITB -2;sub(b(-2),1);0

JUMP -2;0;0

COPY -7;6;0

EDITB -1;sum(b(-1),2);0

JUMP com(b(-2),190,3,3,-2);0;0

SPLIT 1;0;0

JUMP -1;0;0

COPY -2;-100;0

COPY -2;-100;0

JUMP -102;0;0

I got placed at line 61 (line 60 if your VNA starts at index 0) and then this is what happened:

Mekal's program spewed a chain of bombs behind and in front of him, going 1 node farther in each direction every 5th round.

My program scanned ahead, starting at the minimum distance that Mekal's program could've been from mine, and every 3rd round scanned 3 spaces forward until I hit a node that had at least 1 non-zero a/b/c value attached. I found that (I think it was actually line 1 - or line 0 if your VNA starting index is 0) in Mekal's program, as planned, and thus jumped to the part where my program started unleashing BOMBs one after the other on each consecutive node where Mekal's program was. However 'Shielded Phoenix' had only gotten around to planting one BOMB when 'Tidal Wave' ran into the BOMB and destroyed itself

To put it bluntly, I dominated :P

Note that Shielded Phoenix has a double-layer of defense, as you'll see if you read through the code ;D Hehe

Sorry Mekal, better luck next time - we learn from our mistakes, and your mistake was inefficiency. Every 5th round your program churned out another BOMB one space further. Remember that there's at least a distance of 30 between each program, too. But yours was a great first program, and I was worried for a bit that your stream of bombs would hit my first couple lines before my program found yours, but there was still 20 or more nodes to go when I nailed your program, so it would've taken you another 100 rounds or so lol

Good game to both of us :P

Link to comment
Share on other sites

  • 0

oh and for one of the later lines of my program, I meant "add" not "sum", I forgot to change that. Luckily the program never had to go the first defense mechanism and run that line

Darn't!!! oh well... Good program :D

I based the Tidal Wave of of your bomber though... but it is all about where my program is located...

Actually with my program 20 in front of your last line, I would still win, and being 15 apart isn't even allowed, the current limit is 30 to 170 apart :lol: I have some recommendations to improve if you want to hear em. It was a good first program though :D

Link to comment
Share on other sites

  • 0
oh and for one of the later lines of my program, I meant "add" not "sum", I forgot to change that. Luckily the program never had to go the first defense mechanism and run that line

Actually with my program 20 in front of your last line, I would still win, and being 15 apart isn't even allowed, the current limit is 30 to 170 apart :lol: I have some recommendations to improve if you want to hear em. It was a good first program though :D

I got very simular results on my emulator :D THough Mekal was not even half way to Unreality's program

Edited by taliesin
Link to comment
Share on other sites

  • 0

I realized that the first defense mechanism of Shielded Phoenix wasn't sending the BOMB far enough out :o This is fixing it, and fixing the "sum" mistake:

Shielded Phoenix

JUMP 2;0;0

BOMB 27;0;0

JUMP com(com(a(a(-1)),b(a(-1)),a(a(-1)),1,1),0,1,3,3);0;0

EDITA -2;add(a(-2),3);0

JUMP com(a(-3),168,4,4,-2);3;0

COPY -4;sub(a(-4),b(-1));0

EDITB -2;sub(b(-2),1);0

JUMP -2;0;0

COPY -7;8;0

EDITB -1;add(b(-1),2);0

JUMP com(b(-2),190,3,3,-2);0;0

SPLIT 1;0;0

JUMP -1;0;0

COPY -2;-100;0

COPY -2;-100;0

JUMP -102;0;0

for those that don't get what it does:

1) starting 30 spaces away from its starting line, it scans every 3rd line for nonzero a/b/c values to look for the opponent's program

2) when it finds it, it jumps to a new section of the program which unloads BOMBs at each node following the next, ripping into the opponent's program until they're dead

3) the 'shield' part of the name is all the defense mechanisms. First, if the scanning somehow misses the opponent's program and hits 168 lines forward (closest multiple of 3 to the limit of where the other person's program could possibly be) and still hasn't run into it, it jumps forward to avoid the scan from locating itself and then BOMBing itself

4) in the first defense, it begins by re-BOMBing every second space after the end of the program, hoping to nail the opponent somewhere

5) in the second defense, if the secondary BOMBing from the first defense wraps around and approaches the beginning of the program, it jumps forward and then copies two lines about 100 nodes backward, then jumps to those lines. The lines are "split 1" and then "jump -1", causing the program to copy itself a bunch of times until 5 executors are bouncing back and forth between those two lines, so any wide-spread BOMBers are likely to miss and if they do hit somehow, there'll be a few rounds before the death

I'm working on a few ways to make Shielded Phoenix even better, though I should also get working on a new one so that I have the element of surprise :P

Link to comment
Share on other sites

  • 0
I got very simular results on my emulator :D THough Mekal was not even half way to Unreality's program

Yeah that was just a prediction I made, ie, IF mine had been placed 15 ahead, I would still win :D -- but for actual results:

did you test the battles on posts 112 & 115 on your emulator? They should be exactly the same as what mine, or there's an error in your emulator :D

oh and I added a 'round counter' to mine to keep track of rounds

Link to comment
Share on other sites

  • 0
Yeah that was just a prediction I made, ie, IF mine had been placed 15 ahead, I would still win :D -- but for actual results:

did you test the battles on posts 112 & 115 on your emulator? They should be exactly the same as what mine, or there's an error in your emulator :D

oh and I added a 'round counter' to mine to keep track of rounds

I think i have a few ideas to make my stuff a bit better... but i would still like to hear yours...

Edited by Mekal
Link to comment
Share on other sites

  • 0
I think i have a few ideas to make my stuff a bit better... but i would still like to hear yours...

For one, I would have it start both bombings 30ish behind and 30ish in front of your first line, and then jump by 2's, not by 1's. That's if you want to keep the same simple pattern without adding more to it (defense in case the bombs are thwarted by the opponent - such as if the opponent was a Hopper variant - to stop the bombs from advancing if they are getting close to 200 away, which would be back to the start and attacking yourself), etc. It was a good idea to have bombs going in two directions, however that takes an extra COPY and an extra EDIT command

edit for taliesin: see post 120 of this topic :D

Edited by unreality
Link to comment
Share on other sites

  • 0
For one, I would have it start both bombings 30ish behind and 30ish in front of your first line, and then jump by 2's, not by 1's. That's if you want to keep the same simple pattern without adding more to it (defense in case the bombs are thwarted by the opponent - such as if the opponent was a Hopper variant - to stop the bombs from advancing if they are getting close to 200 away, which would be back to the start and attacking yourself), etc. It was a good idea to have bombs going in two directions, however that takes an extra COPY and an extra EDIT command

edit for taliesin: see post 120 of this topic :D

ya... i had already changed it to go by 2... but i hadn't thought about starting 30 away... i'm also going to make it a bit more advanced...

Link to comment
Share on other sites

  • 0
I think i have a few ideas to make my stuff a bit better... but i would still like to hear yours...

@Markel, Modified you program to SMASH Unreality's Pheonix :P

It now jumps two lines at a time when planting bombs to increase the speed of finding opponent.

It also has c values to "0" out some of the code to look for sums of non zero values.

And it places a/b/c on bombs placed to confuse Pheonix

Tidal Wave ( Pheonix Killer Version :P)

copy 5;-1;0; sub(0, add(a(0),b(0))

copy 4;6; sub(0, add(a(0),b(0))

editb -2; con( add(b(-2),-2),-196, -1,add(b(-2),-2), -1) ; sub(0, add(a(0),b(0))

editb -2; con( add(b(-2), 2), 198,6,6, add(b(-2),2) ) ; sub(0, add(a(0),b(0))

jump -4;0;4

bomb 213;32;53

Edited by taliesin
Link to comment
Share on other sites

  • 0
lol @ your sig about Romans. Did you make it up?

Wasn't that line a "famous" line from an English Comady TV Show? I sure one of the English people I work with was telling me "all" about it!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...