Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Generation of random strings  (Read 2202 times)
0 Members and 1 Guest are viewing this topic.
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Posted 2004-09-06 21:58:11 »

Why is there no AI forum?
I think this place will do...
I want to generate random strings based on a user supplied RE.

I want it for my genetic programming module. It generates random programs. Most problem domains have constants, but it varies from domain to domain what the particular constants look like.
I thought the neatest and user freindly way would be for the user to specify a RE for what his constant symbols would look like. Having got that I then need to be able to generate possible constants.
you know the user could say a boolean looks like true|falseor a float looks like (+|-)?{digit}*.{digit}*
I have sat down with javacc a couple of times to do the parsing but its alot of effort for what seems to be a trivial problem.
Anyone got any ideas how I could shortcut writing my own RE parser?
If you want justification of it being a game thing its will be used to create AI algorithms.

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline Mark Thornton

Senior Member





« Reply #1 - Posted 2004-09-07 07:58:58 »

A regular expression doesn't really provide enough information to generate strings. For example, consider "[a-z]*", then how long should the generated string be? One way would be to specify a probability p for having an extra character. Then the string would have at least one character with probability p, at least two characters with probability p*p, etc. You need to associate such probabilities with each * and similar operators in the regular expression.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #2 - Posted 2004-09-07 09:52:58 »

Quote
Why is there no AI forum?


Yeah, my thoughts too Wink
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=suggestions;action=display;num=1076792118

Quote

I want to generate random strings based on a user supplied RE.

I want it for my genetic programming module.


Nope - that is the LAST thing you want to do. GP has nothing to do with generation of strings, and if you are trying to do it that way it's no wonder you're having a hard time.

GP is all about generating AST's (Abstract syntax trees). Why? Because this is what the javac parser is converting your raw text into when it parses: GP skips the whole textual-source-code stage (because it is entirely useless and just makes things slower to execute). There is tonnes of google info on AST's, but they're really a very very simple concept, so you should have no problems.

So, forget about generating strings Grin. It's a complete waste of time - and once you move to AST's you'll find it's much easier.

malloc will be first against the wall when the revolution comes...
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #3 - Posted 2004-09-07 17:00:37 »

Jesus Christ. This happens whenever I mention this, no matter how much I try to assure people I know what I am talking about.
Yes I know expansion like * & + need a probablility. I have that allready. Makes the strings act like a possion distrabution.
Yes I know what an abstract syntax tree is. No I am not having a hard time implementing a GP.
I have it all working, infact I have made some rather clever modifications to the standard algorithm to make mine more effecient.
But in a problem domain some of the symbols in a language are constants.
Like for example a drawing domain.
The operations are things like
move pen vertically X
and change pen colout Y
The user needs to be able to say what can fit in the X and Y slot.
For X it would be a float
for Y it would be
{red|green|blue}
Now some people think I should make the user to specify a class to be loaded dynamically. This means the user has to write trivial enumeration classes for his problem domains... very naff
It would be much better if the user could put int his symbol definition
<constant>
     red|gree|blue
</constant>
<constant>
     (+|-){digit}*.{digit}*
</constant>
(infact my system is slightly more complex than that becuase my GP produces typed syntax trees)

Right hopefully someone will now beleive me when I say I would like to program a class that parses a RE and generates random string from that definition.
I am very capable of writing such a parser, having written compilers. But it is still not a small peice of work even so. And really I would like it it to be super compatable with the inbuild java RE support. So does anyone know how I could shortcut this? Maybe preverting the Pattern class itself. I have looked at the source but its a bit weird so I dunno.
I am coming to the conclusion I think that I will have to bite the bullet and get javacc out.  Argh. It depresses me though. MAybe I could build a java top down parser quicker but then thats alot less maintanable.




Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #4 - Posted 2004-09-07 18:10:17 »

Quote
Jesus Christ. This happens whenever I mention this, no matter how much I try to assure people I know what I am talking about.


Sorry for misunderstanding. However, it was partly your own fault for presenting a poorly explained problem with little or no explanation, a lack of use-cases, and a brief allusion to a subject where many people think they need something like this when they don't. I made an assumption that you were doing as many people do - not that you were doing something much more esoteric.

Quote

I have it all working, infact I have made some rather clever modifications to the standard algorithm to make mine more effecient.
But in a problem domain some of the symbols in a language are constants.
Like for example a drawing domain.
The operations are things like
move pen vertically X
and change pen colout Y
The user needs to be able to say what can fit in the X and Y slot.
For X it would be a float
for Y it would be
{red|green|blue}


There is nothing you describe here that differs from standard AST-based GP. Since you still haven't explained fully, it's not entirely clear whether your terminals are all strings (i.e. user can type them into a soft config file) although I get the impression this is your approach.

In that case, you need them to declare typing some other way - which you haven't mentioned - or be using a type-inference system a la ML. Neither sounds particularly desirable; hence I'm still unsure  what you're trying to do (which makes it hard to suggest helpful approaches).

Quote

Now some people think I should make the user to specify a class to be loaded dynamically. This means the user has to write trivial enumeration classes for his problem domains... very naff


"Naff"? Or just "obvious, easy, and standard practice"?

Personally, for java, I'm a fan of each terminal and non-terminal being a UID-keyed immutable object, with children of non-terminals being passed in as args to the evaluate method, so that your AST's can be stored as something extremely compressed (both in memory and when serialized) hardly more verbose than a compressed bit-string (using a sensible tree-to-string conversion) but are still simple to execute using an execution layer you only need write once and never fiddle with.

"pure OOP" class structures are much easier to write and to debug, but the memory requirements are punitive in java, unless you start getting fancy and using structs or something (which I've wanted to try for a long time now, but never had the spare time yet).

Quote

<constant>
     (+|-){digit}*.{digit}*
</constant>
(infact my system is slightly more complex than that becuase my GP produces typed syntax trees)

Right hopefully someone will now beleive me when I say I would like to program a class that parses a RE and generates random string from that definition.


I agree with the earlier poster that this seems a poorly thought-out aim. I'll provide you with one that just provides a plus followed by an infinitely long string of digits followed by a dot followed by another infinitiely long string of digits (the only limits being how long before your system runs out of RAM to hold the number of digits I'm amassing). This is entirely consistent with the regexp you cited, yet I struggle to see how it's anything but useless to you.

Now, if you were to guarantee a finite limit on the number of occurrences of each state [sorry, can't remember the mathemetical term /me blushes]
(thereby severely limiting the number of regexps possible) then I could suggest sensible implementations. But then, if that were all you wanted, it seems you wouldn't be asking, because that's pretty trivial to code Huh.

Quote

Maybe preverting the Pattern class itself. I have looked at the source but its a bit weird so I dunno.


If my last para is indeed what you want to do then I agree you'd want to try and take advantage of the FSM that is pre built when you instantiate a pattern; you might want to take a look at the open-source Apache regexps which might be easier to break apart (nb: I *think* that's what became of the OROinc regexp implementation, which was a pretty good one).

But then again, I still don't understand what you're after, so ...

malloc will be first against the wall when the revolution comes...
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #5 - Posted 2004-09-07 18:15:09 »

Quote
A regular expression doesn't really provide enough information to generate strings.


...because regexp's typically match sets of strings with infinite size, and infinite sets tend to be rather impractical as a source of data for computer programs?

(I'm not being facetious - people do try, and have genuine problems; c.f. the practical problems of the bracket-matching problem, and the numerous instances where people have ignorantly attempted to "solve" this using finite RAM).

malloc will be first against the wall when the revolution comes...
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #6 - Posted 2004-09-07 18:27:06 »

Hehe.
I jsut want the the String generator for the use in generating constants. The nodes at the bottome of the AST. Nothing to do with the AST representation. To generate possible terminals of the language for the users problem domain.
i.e
IDENTIFIER
float
red|green|black

Yes they could be infinite. A float potentially could be infinite on a perfect computer. But we have a probability to control how big they are (and I don't think I will allow the user to set it)

Yes of course you havn't seen what I have done thats interesting to the GP algorithm. I hope to write a paper on it.

Really I shouldn't of mentioned anything to do with the GP. Jsut when I do that people look at me weird and say, why do you need to generate random strings based on a RE. So I was hoping to avoid that lengthy debate. Now I have plunged myself into the largest one yet!

Even dispite your tone. I do beleive you might be on to something with the apache link. I shall check it out

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #7 - Posted 2004-09-07 18:33:13 »

Yeah I wanted to do it with RE. Becuase every programmer in the world knows what a RE is. Plus almost every language has their tokens decribed as regular expressions.
Thus allowing the user to specify his tokens in his arbitary problem  domain as RE is very user freindly.
Yes there is a mismatch becuase how big should the GP be allowed to generate tokens. And so the obvious though is to have  a probability of an expantion. Thus the strings can still potentially be of infinite length whihc is nice mathmatically. But statistically over a lanrge amount take up an most probably size of memeory.
Right I got people bloody come round annoying me
gotta go

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #8 - Posted 2004-09-07 18:59:29 »

Quote
Yes there is a mismatch becuase how big should the GP be allowed to generate tokens. And so the obvious though is to have  a probability of an expantion. Thus the strings can still potentially be of infinite length whihc is nice mathmatically. But statistically over a lanrge amount take up an most probably size of memeory.


No, not "obvious", but IMHO "stupid", unless you use a clamped distribution to strictly limit the number of times you can get stuck in any particular state or repeating set of states - which is precisely what I described, only using different terminology.

You don't want to deliberately write a program that has a known guarantee of crashing, depending only upon a random number!

Aside from the fact that any non-zero probability is a possibility even on the very first run, my experience is that GP tends to exercise everything "sooner or later". I found a VM bug in Sun's modulus operator this way (although their engineers didn't like my test case, which consisted of a GP which "sooner or later" would exercise the bug).

For reference, the last time I did GP for a game (part of my university work) I generated somewhere in the region of:

- 10k population size
- average of 40 terminals per individual
- average of 10% terminals in each generation "new"
- one generation every 20 minutes (IIRC; I had a slow computer, though...)

So, I would generate somewhere around 100k terminals per hour, and a single run would be around 4-8 hours.

One million samples tends to make low probabilities appear quite often Smiley. I believe this is why I found a bug which they - to that point - hadn't; it was dependent upon some combination of arugments to the java modulus operator (removing the modulus operator and writing a modulus function by hand instead removed the VM crash permanently).

malloc will be first against the wall when the revolution comes...
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #9 - Posted 2004-09-07 21:55:14 »

I don't think its likely to create huge Strings
take
(a)*

If we have a probability of a * expanding at say .75 This numbe ris fixed for a GP run

I intend the machine to go

lets look at the (A)* shall we expand (roll the dice .75 chance of yes)
ok yes

so return string is now a
with an (a)* expansion left

shall we expand it (roll dice - yes)

now the string is aa with an unexpanded a*

shall we expand it
blah blah blah.

Whats the chances of getting .75 a million times in a row
Very unlikely.
Plus the string is in a buffer, a dynamic ADT so whats the problem?

I am not trying to decide how long the string is gonna be by one roll of the random class. It will have to keep rolling a random for each expansion of a *. I planned to hard code the expansion chance at .5, though I think the user should be able to overide that. (Its a poisson distrabution as mentioned earlier)

The possibiliy of it generating a string so long as to crash the VM is probably lower than the chance a cosmic ray will hit my RAM and currupt a bit therfore crashing my computer. Its ok do do things with stats as long as you know what you are doing.
You know systems like RSA don't generate real provable prime numbers. We all know prime numbers are expensive to come by, so how does it get those prime numbers?
By conducting independant mathmatic tests on a potential prime number until they reach a very high probability that the number in question is a prime number. The argument being that computers are mechanical devices and have a chance of failure anyway. Once you exceed that probability it doesn't matter. The thing that will make you program go wrong will statistically not be your program, but the computer itself.
Stupid idea my arse blahblahblah



Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #10 - Posted 2004-09-07 22:06:52 »

I mean fairplay. I know what you mean about GP tending to crash the becuase of the slightest statistic bug.
I find this happens alot.
But it won't happen with the method I am trying becuase the chances of it generating a n sized string is
p^n

The critical thing being its an exponetial reletionship.

The chance of of it generating a string 200 characters long is
0.000000000000000000000000025
Which with a billion randomly generated constants ain't gonna happen.
(and rememebr that most of the stuff you have floating in your population isn't randomly generated, its most is passed from parent to child , mutation is a low probability anyhow)

(yeah and before someone smart arse says that the probability of a 200 or more sized string is the sum to infinity of the subsequant probabilities has not realised its still a exponetial reletionship)

Its the exponetial behavour that stops the VM from being able to much up.

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #11 - Posted 2004-09-07 22:10:16 »

#Sorry I forgot to say that above calculation was based on a .75 chance of expantion. A figure so rediculously over high what I would set it in paractice to demonstrate the saftey of the system.
(the chance of 300 letters is 3 * 10 ^ -38 we will soon get into the running time of the universe area)

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #12 - Posted 2004-09-07 22:47:46 »

here is the proper calculations (there were a few minor errata earlier)
http://users.aber.ac.uk/ttl0/proof.pdf
I hope blahblahblah you can admit defeat graciously. I would love to hear an apology for the stupid remark....

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #13 - Posted 2004-09-07 23:21:58 »

EDIT: in relation to an apology, I don't care either way. I have an opinion that your basic approach is not "obvious" but "stupid" (as I said); that opinion has not changed - although the details you are beginning to come out with may suggest that you are less likely to suffer from it than I assumed.

The biggest problem here is that I still don't see why you want to use regexps to specify terminals (which I've been trying to get out of you). It just seems an inappropriate tool for the job.

Aside from that, AFAICS there's no issue of "defeat" or "victory"  - as I pointed out, you provided insufficient information on what you were doing etc for other people to be of much help, and I've been guessing ever since.

Perhaps your users aren't going to fiddle much, perhaps you will only have one string per individual - who knows? (you haven't really told us - e.g. I've had to guess what mutators, selectors, rankers, and scorers you're probably using). IME you can easily end up with a vast number of these terminals, and with regexps being arbitrarily complicated, and with the user able to set the probability of carrying on to a stupid figure, I still believe it's not a sensible core design.

Personally, I like to leave GP running for large amounts of time unattended; anything that risks it crashing is - IMHO - a design flaw. Checkpointing only gets you so far (because it usually slows down the evolution process by a considerable amount; although, c.f. above, I think using NIO one could potentially get that down to a negligible amount).

When it comes to probability-based crashes, a non-zero probability could happen 10 times in a row. With the vast numbers of iterations that GP tends to do, it could (for instance) end up happening within 2-4 hours on 10 runs in a row with a not spectacularly unlucky chance (this is not in reference to your figures, but relating probability to the real-life problems I've had). I managed (eventually) to tweak a run so that it crashed every single time within 9 hours, and usually within 3 hours, on that difficult-to-trace modulus bug. It was probably a very small probability of occurrence.

malloc will be first against the wall when the revolution comes...
Offline t_larkworthy

Senior Member


Medals: 1
Projects: 1


Google App Engine Rocks!


« Reply #14 - Posted 2004-09-08 00:26:41 »

Apology accepted.

I want to use RE becuase they are easy for a user to write in a config file (I am sure I mentioned this a few times). Any computer literate able to use my genetic programming module will know the syntax of regular expressions. Hence the user can create a new behavour of a constant very quicky.
Take for instance a float, there is a class inbuilt in my GP for handling floats (though the user could provide his own).
But think of all the problem domains a float could exist in.
Probabilities: the float needs to be between 0 and 1
Square roots: the float needs to be posative (well actually ...)
angles: the float is between 0+-2*PI
Simple you cry. Why don't you hardcode in the config file for dealing with floats an upper and lower bound?
And the same for integers as well?
And erm. What if the user perhaps wants to tune his GP.
Maybe he would like the nubmers to come out in a normal distribution. What then?
And then along comes a problem in the complex domain. I don't include any support for complex types. So then the user has to create his own data type, but then he cant configure what the constants look like in config file. He will need to do that in more dynamically loaded classes. What if he then has to reuse his data type in other problem domains. More coding class files?
The way mine works is data is constructed from a String. Floats just parse the string value etc. etc. And so will custom data types. The GP needs to randomly generate the data types for constants so the use of RE was so that the user could have one way of configuring all data constants in any problem domain for any data type.
Take for insance my complex data type
the user could specify it as
(digit)*.(digit)* ((+|-)(digit)*.(digit)*)?
its a great way to do it coz its so damn flexable. And any user could do it.
if you wanted probabilities
0.(digit)*
things like angles and normailized distributions require a little more creativity
an angle between 0 and PI
((0|1|2).(digit)*)|((0|1|2).(digit)*)|((0|1|2).(digit)*)|(3.0(digit)*)
Will give you a uniformy distributed number between 0 <= x <  3.1. Not perfectly PI. but a good approx.
An aproximatly uniformly distributed number between 0 and 1:
0.(1|2|2|3|3|3|4|4|4|4|5|5|5|5|5|6|6|6|6|7|7|7|8|8|9)
again an crude approx (maybe wack a {digit}* on the end for good measure). But certainly a great way to influene the GP the way it is intended.
Overall I think the use of regular expessions for describing what constants sybols is a stoke of genius. Thinks like GP need to work on things other than number problems. Regular expressions can work with non-numerical data! The only think more expressive than them would be for the user to write a grammer for his constants initializer. But thats unusable. A RE is taught to every programmer in the world. Its so usable and still so expressive.

Agreed they are not 100% perfect for the job there are a few niggles with them like when to call it a day on the * expansions. I think I have proved though beyond doubt that problem has a decent work around. But then I want to minimize the amout of reading up he has to do to use the product.
If he decides to overwrite the default expansion probability to 1, then thats really his fault for messing with something he did not need to know about and not learning what it meant first.

Runesketch: an Online CCG built on Google App Engine where players draw their cards and trade. Fight, draw or trade yourself to success.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #15 - Posted 2004-09-08 10:54:59 »

Quote

But think of all the problem domains a float could exist in.
Probabilities: the float needs to be between 0 and 1
Square roots: the float needs to be posative (well actually ...)
angles: the float is between 0+-2*PI
Simple you cry. Why don't you hardcode in the config file for dealing with floats an upper and lower bound?
And the same for integers as well?
And erm. What if the user perhaps wants to tune his GP.
Maybe he would like the nubmers to come out in a normal distribution. What then?


Ah, now I'm following you Smiley. What I've always done is provide a PDF interface (nothing to do with Adobe Wink) and people write their own classes that use a PDF and a data-set and plug them in. Easy to create, easy to maintain, highly reusable, efficient, and extremely powerful.

e.g. You can apply any generic pdf to any enumerated set easily enough.

e.g. You can apply pseudo-enumerations (just enough to be able to continue using the generic pdf's) to sets such as "any float representable in java"

e.g. you can compose mulitple sets and pdf's into new ones - e.g. a generator that uses an exponential pdf to decide whether to select from a uniform float, a uniform int, or a quadratic-distribution of doubles.

Quote

Thinks like GP need to work on things other than number problems. Regular expressions can work with non-numerical data! The only think more expressive than them would be for the user to write a grammer for his constants initializer. But thats unusable. A RE is taught to every programmer in the world. Its so usable and still so expressive.


But you've (literally) described nothing more than a pdf with a set of values - and this is a concept that is probably more widely recognised than regexp's (well, in my country, teenagers are taught a lot about pdf's before leaving school). Some of the examples you were giving quickly look horrible to maintain, especially when compared with writing generic 3-line algorithms.

Is there something like you don't want your users to write any java code? If so, you could accept pdf's in arbitrary scripting languages instead. I suspect your regexp's will just get more and more complicated over time, with you/your users effectively trying to use regexp's as a full-blown programming language, and eventually you'll realise that's what you've ended up doing, and will want to move to a real language instead.

malloc will be first against the wall when the revolution comes...
Offline zingbat

Senior Member




Java games rock!


« Reply #16 - Posted 2004-09-08 11:13:12 »

This reminds me of L-out for generating trees and plant geometry. Except that L-out uses grammar like rules instead of REs.
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #17 - Posted 2004-09-08 11:48:34 »

Quote
This reminds me of L-out for generating trees and plant geometry. Except that L-out uses grammar like rules instead of REs.


...and L-out is a much simpler/more tightly constrained problem domain IIRC? (so in most cases it works well to be using a simpler tool)

malloc will be first against the wall when the revolution comes...
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (24 views)
2014-07-24 01:59:36

Riven (24 views)
2014-07-23 21:16:32

Riven (18 views)
2014-07-23 21:07:15

Riven (21 views)
2014-07-23 20:56:16

ctomni231 (50 views)
2014-07-18 06:55:21

Zero Volt (45 views)
2014-07-17 23:47:54

danieldean (36 views)
2014-07-17 23:41:23

MustardPeter (39 views)
2014-07-16 23:30:00

Cero (56 views)
2014-07-16 00:42:17

Riven (55 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!