View unanswered posts | View active topics It is currently Tue Apr 21, 2026 3:51 am



Reply to topic  [ 9 posts ] 
 Easy way to track Fig Grids in TWX 
Author Message
Gameop

Joined: Thu Apr 19, 2007 2:10 am
Posts: 5
Unread post 
Hi All,

I came back to TW a few weeks ago after 10+ years gone. Been having fun so far, and am really liking TWX Proxy.

I'm a Programmer (MS SQL), so I like writing my own scripts to accomplish exactly what I want without any unnecessary fluff. There are a lot of good public scripts out there, but most do not seem to be as efficient as they could be.

A problem I have been having for a while has been finding a way to track my Fig Grids in a dynamic way that can be accessible to all Scripts that I run.

I started out loading my FigList at the start of every script I run. In a 20K Sector Game, this is inefficient as hell, and makes testing the scripts a nightmare when you have to wait for the Figlist to load just to see if one part of unrelated code that was changed had the desired effect.

Also, this method was great for adding Figs to the FigList Array for use within the main Script, but keeping track of Figs that are destroyed while the main Script is running is a logistical nightmare.

I thought I found a solution when I set up a System Script to do: setArray $FigList SECTORS

Then I could just track my Figlist Array in a seperate System Script. Unfortunately (I did not know this at the time), it appears the Variables set by one script are not visible to other scripts that are running, even though all active Variables are visible from the "Menu> Script> V" command, regardless of which script created them. Go figure.

I've spent the last couple days searching around for a solution. I've found a dozen or more posts asking for a way to do it, but none that actually had a solution. I finally found a solution a couple hours ago and wanted to share it in case anyone else was still looking for something similar.

If this solution has been found before, great, but I could not locate it anywhere. ;)

The answer lies in the setSectorParameter and getSectorParameter commands:

The code example below is what I came up with:
(Comments where I thought they might be needed)


### ============================================================ ==========

# Dark Jester's Fig Tracker
# Set this as a System Script so we don't accidentally Terminate it
systemScript

:FigTrackerStartup
# Wipe out any info from previous times this Script has run.
# This only takes 3-7 seconds for a 20K Universe on my machine

  setVar $i 1
  while ($i <= SECTORS)
    setSectorParameter $i "Figged" "0"
    add $i 1
  end

:FigFileRefresh
# We need fresh Fig Information

  echo "** " ANSI_10 "Refreshing Fig Info - Please Wait ...*"
  send "G"
  waitOn "==========================="

:CycleRefresh
# Same as most other scripts that get Fig Info for a FigList Array or Fig File

  if (CURRENTLINE = "=========================================================== ")
    goto :CycleRefreshNext
  else
    getWord CURRENTLINE $FigSector 1
    getWord CURRENTLINE $FigListFinished 2
  end
  if ($FigListFinished = "Total")
    goto :FinishFigRefresh
  end

# This is the difference. Instead of using an Array like "setVar $FigList[$Sector] 1"
# setSectorParameter sets a 'Variable' for the specified Sector within the TWX Database itself.
# This Variable is visible to all Scripts via the getSectorParameter command.

  setSectorParameter $FigSector "Figged" "1"

:CycleRefreshNext
# Get the next Fig for the Refresh
  setTextLineTrigger GetFigInfo :CycleRefresh
  pause

:FinishFigRefresh
# Done loading the Fig Info into the Database
  echo "** " ANSI_10 "Fig Info Refreshed - Fig Tracker Running ...*"

:FigTrackerWait
# This is the Idle Script that watches for Figs that are Destroyed.
# I could probably do a further check to make sure the Player actually attacked
# before erasing the Fig from the Database, but 99.99% of the time, when a player enters
# a Sector with a Fig in it, they kill it.

  setTextLineTrigger PlayerFigHit :PlayerFigHit "Deployed Fighters Report Sector"
  pause

:PlayerFigHit
# A Player entered the Sector
  killTrigger PlayerFigHit
  getWord CURRENTLINE $FigHitCheck 1
  getWord CURRENTLINE $SectorHit 5
  stripText $SectorHit ":"
  if ($FigHitCheck = "Deployed")
  # Make sure it was a Player. This sets the Sector to 'No Fig' for Script purposes.
    setSectorParameter $SectorHit "Figged" "0"
  end
  goto :FigTrackerWait

### ============================================================ ==========


And that's it. The Script only needs to be run once when you log in, and it will update itself after that by removing any Figs that are destroyed (by Players). Any Script you run can access this information since it is stored as Static Info in the Database, not as a temporary (Invisible) Variable.

Adding Figs to this 'Array' can be done in the individual scripts that you run. Any time your other Scripts place a Fig, have them also send the Command: setSectorParameter $FigSector "Figged" "1"

Other Triggers can be set in the Idle Section to track Ferrengi Fig Hits, or Extern's MSL Fig Hits.

To pull the data back out of the Database, say in a Breadth Search for Near Fig:
(Breadth Structure borrowed from Elder Prophet)


### ============================================================ ==========

:NearFigSearch
  setVar $Start $CurrentSector
  setVar $MaxDistance 15
  setVar $Top 1
  setVar $Queue[$Top] $Start
  setArray $Checked SECTORS
  setVar $Checked[$Start] 1
  setVar $Bottom 1
  while ($Bottom <= $Top)
    setVar $Focus $Queue[$Bottom]
    getDistance $DistanceTo $Start $Focus
    if ($DistanceTo > $MaxDistance)
      goto :NoFigFound
    end
    setVar $k 1
    while ($k <= SECTOR.WARPCOUNT[$Focus])
      setVar $Adjacent SECTOR.WARPS[$Focus][$k]
      if ($Checked[$Adjacent] = 0)
        getSectorParameter $Adjacent "Figged" $FigCheck
        if ($FigCheck = 1)
          setVar $FigSector $Adjacent
          goto :FigFound
        end
        add $Top 1
        setVar $Queue[$Top] SECTOR.WARPS[$Focus][$k]
        setVar $Checked[$Adjacent] 1
      end
      add $k 1
    end
    add $Bottom 1
  end
 
:NoFigFound
  echo "No Fig Within 15 Hops."
  return

:FigFound
  echo "Fig Found in Sector: " & $FigSector
  return

### ============================================================ ==========


I hope this helps anyone that was not aware of it. :)

If there are any questions or comments, give a shout.

Thanks,

-Dark Jester


Wed May 30, 2007 8:09 am
Profile
Veteran Op
User avatar

Joined: Thu Jun 02, 2005 2:00 am
Posts: 5558
Location: USA
Unread post 
Hehe, welcome back and welcome to the club... just replied to you on grimy. I'll copy/paste it here.

Quote:
Welcome to the parm club. =)

You're working with old sources . Those of us that actively script have been using them for nearly a year now. Check the site in my sig and the way I do stuff w/ quickfigs. We've been using "FIGSEC" as the standard parm name so that scripts are portable. It'd be nice to keep that standard. =)

The problem you're going to run into is one of user logistics. Ensuring that people have every single script they need to manage the myriad of details, like monitoring fig hits, makes the seperate system script approach hard to work with. There may also be issues of concurrency to deal with, for instance how can you insure that the fighits are being recorded by the systemscript before a torper loads the data? In a simple adj torper you could avoid that w/ algorithm hacks, but an anticipation torper is going to get confused all to heck if fig positions are tracked out of order.

This is why I usually track fighits within the scripts themselves. It's not as modular, but it eliminates both issues.

The BFS has been replaced with new 2.04 commands. getNearestWarps and getAllCourses. A nearfig search like that w/ all of the setArrays needed to keep it fast will still be much slower than the pointer-based vers now available. Case in point... it makes a call to $Queue array but there's no static definition of it, dynamic arrays are painfully slow and static arrays still take substantial time to initialize. The tree stack can be initialized much more efficiently as an internal and all you have to do is crawl it.

Sadly there are no global vars within TWXproxy, but you can emulate them with parms or loadvar/savevar. If you cache your db in memory parms will be faster, so you can write the var(s) to a parm attached to terra and pass them back and forth. You'll just need to deal with the concurrency problem if you go that route.

Oh, and you can use TRUE and FALSE for writing parms if you want. TRUE evals to 1, FALSE evals to 0, and you don't need quotes. Not really an issue since it's a loosely-typed language, but it makes it easier to do comparisons. There was a bug in an earlier release where parms got corrupted and you'd write a boolean but pull an int. I think that was fixed, I haven't seen it in the latest release, but I still check for it jIc it returns. Last thing you want is to be pdropping and have your script harf before the planet is returned.

You don't need to initialize parms since you could write TRUE/FALSE based on the figdata, but it's not a bad idea to init them as a group. Parms are stored as extra strings in the DB, so the further down on the list the longer it'll take for them to load. Put the important stuff up front and initialize it at the start of the game and you'll cut the time load.


Script I have on navhaz... and posted on classictw...

Code:
#  ------------------------------------------------------------ -------
# Dnyarri (Singularity)'s nearest unfigged sector finder.
# Useful little script that takes advantage of 2.04's BFS function
# to find the nearest unfigged sector in your DB. Requires ZTM.
# Uses Quickfig's FIGSEC parameter for fig tracking so you'll need
# that too.
#
# More scripts and info at http://www.navhaz.com
#  ------------------------------------------------------------ -------
# Search from where?
:get_start
getInput $start "Sector to search from (ENTER = your TA)? "
if ($start = "")
    gosub :get_current_sector
    setVar $start $current_sector
end
isNumber $result $start
if ($result < 1)
    goto :get_start
end
if ($start < 1) OR ($start > SECTORS)
    goto :get_start
end

# Do the search
echo ANSI_13 & "**Searching...*"
getNearestWarps $stack $start
setVar $idx 1
while ($idx <= $stack)
    setVar $this_sec $stack[$idx]
    getSectorParameter $this_sec "FIGSEC" $figged
    if ($figged = TRUE) AND (PORT.EXISTS[$this_sec] = TRUE) AND (PORT.BUYFUEL[$this_sec] = FALSE) AND ($this_sec <> RYLOS) AND ($this_sec <> ALPHACENTAURI)
           echo ANSI_14 & "Nearest figged fuel port to " & ANSI_11 & $start & ANSI_14 " is " & ANSI_10 & $stack[$idx] & ".*"
           if ($start = $this_sec)
               setVar $course_idx 0
               setVar $lane[1] $this_sec
           else
               getCourse  $lane $start $this_sec
           end
           setVar $course_idx 1
           while ($course_idx <= ($lane+1))
                if ($course_idx = 1)
                      echo ANSI_2 & $lane[$course_idx]
                else
                      echo ANSI_9 & $lane[$course_idx]
                end
                if ($course_idx <= $lane)
                      # Print hop seperator if we should
                      echo ANSI_11 & ">"
                end
               add $course_idx 1
           end
           echo "**"
           send #145
           halt
    end
    add $idx 1
end

echo ANSI_14 & "No figged fuel ports found!**"
send #145

#  ------------------------------------------------------------ -------
halt
#  ------------------------------------------------------------ -------
# Get current sector - I'd use CURRENTSECTOR but it's wrong a lot.
:get_current_sector
setVar $current_sector 0

:current_sector_loop
isNumber $result $current_sector
if ($result < 1)
    send "/"
    waitFor #179
    setVar $line CURRENTLINE
    replacetext $line #179 " "
    getWord $line $current_sector 2
    goto :current_sector_loop
end
if ($current_sector < 1) OR ($current_sector > SECTORS)
    send "/"
    waitFor #179
    setVar $line CURRENTLINE
    replacetext $line #179 " "
    getWord $line $current_sector 2
    goto :current_sector_loop
end
return
#  ------------------------------------------------------------ -------

_________________
May the unholy fires of corbomite ignite deep within the depths of your soul...

1. TWGS server @ twgs.navhaz.com
2. The NavHaz Junction - Tradewars 2002 Scripts, Resources and Downloads
3. Open IRC chat @ irc.freenode.net:6667 #twchan
4. Parrothead wrote: Jesus wouldn't Subspace Crawl.

*** SG memorial donations via paypal to: dpocky68@booinc.com
Image


Wed May 30, 2007 8:34 am
Profile ICQ WWW
Gameop

Joined: Thu Apr 19, 2007 2:10 am
Posts: 5
Unread post 
Now that I think about it, I did see your script when I was looking for examples of Breadth Searches last week. I didn't realise it was using  get/setSectorParameter though. Could have saved myself a lot of time reinventing the wheel.


Wed May 30, 2007 8:42 am
Profile
Veteran Op
User avatar

Joined: Thu Jun 02, 2005 2:00 am
Posts: 5558
Location: USA
Unread post 
Nah, it's always good to get practice in.

I definately feel the pain of using fig files... a couple years ago I was manually checking a list of 500 sectors against figged sectors. I thought "wow, finally a way to avoid that" only to have it spend a good 60 seconds just to load the fig file... every single freaking time. Parms rock up a storm for stuff like this.

_________________
May the unholy fires of corbomite ignite deep within the depths of your soul...

1. TWGS server @ twgs.navhaz.com
2. The NavHaz Junction - Tradewars 2002 Scripts, Resources and Downloads
3. Open IRC chat @ irc.freenode.net:6667 #twchan
4. Parrothead wrote: Jesus wouldn't Subspace Crawl.

*** SG memorial donations via paypal to: dpocky68@booinc.com
Image


Wed May 30, 2007 8:47 am
Profile ICQ WWW
Commander
User avatar

Joined: Tue Oct 07, 2003 2:00 am
Posts: 1134
Location: Augusta, GA
Unread post 
Hey Dark Jester, and welcome back.

I think you'll find plenty of knowledgeable scripters chomping at the bit to answer most questions you might have. Really, I don't even think we get tired of answering the same old simple questions... so long as the same person isn't asking them over and over again

Anytime you need something like that answered, feel free to drop a blurb in here, even as you continue hunting an answer on your own. I think you'll be surprised at the timeliness of the responses, and the quality of the posts.

There were numerous changes introduced in version 2.04, so any scripts more than 6 months old may not use the latest and simplest techniques. There are routines that took dozens of lines of code before 2.04 that now only take a fraction of that. Heh, I wrote a quickstat routine in 2.04 that was like 10 lines, compared to a previous best of 50-ish.

So, welcome back, keep the scripts flowing, and remember that that we sign in each day hoping for the chance to answer a script question

+EP+

_________________
Claim to Fame: only guy to ever crack the TW haggle algorithm, and fig/shield/hold price formula, twice.


Wed May 30, 2007 8:57 pm
Profile WWW
Gameop

Joined: Thu Apr 19, 2007 2:10 am
Posts: 5
Unread post 
Hiya ElderProphet,
Sounds good to me. I just started looking into some of the changes from 2.03 to 2.04 after reading Sing's post above about the changes to breadth searches. It made me realize that a lot of the information I have been using for reference material is really outdated. ;)
Most of the games I have played so far since coming back have been solo unlimited games while I relearn everything. Most of my scripting work so far has been tailored to those games. Eventually once I get my feet firmly in place again I will move to the turn limited games that I used to play all the time. ;)
These are some of the different scripts I have made so far:
1. World Planet Trade: Not much profit compared to SST, decent for a blue though.
2. World Planet Fuel Buy-Dumper: P-Warps to nearest untraded Sxx Port, upgrades, and buy-dumps all of the fuel. Repeat until Planet is full and return to base. Will sell excess Org and Equip on the planet if it can.
3. A Planet-Grid script that uses P-Warp and Surround Sector to expand an existing Grid. Locates nearest unfigged sector, and then checks to see if we have an adjacent fig to that so we can Grid it. (and any other unfigged sectors adjacent to the one we warp to) Very fast, and reasonably safe.
4. A Resource Mover that moves all different resources between planets at the fastest speed I could manage. (Ore, Org, Equ, Cols, Figs, Shields) - Currently it will transfer 100K Fuel in a little less than a minute with a 250 Hold ship.
They all work great, though I will be making some improvements based on research after reading Sing's post above.
I’ve found some public scripts that do similar things, or when combined they would accomplish the same goal, but most of them offer more ‘options’ or other wasted code that slows down execution and really isn’t needed for a concise efficient script. In most cases I assume this is because they are Public scripts. The extra stuff seems to be put in to make them “Idiot Proof” and widely adaptable, but to me it just lowers efficiency. ;)
===
My current project is Optimizing the Turbo-SST Script. It works fairly well in it's base form, but it takes some unnecessary steps and uses inefficient methods that waste quite a bit more time than it should. There are also a couple bugs that will cause the script to hang. The original version was pulling in around 125 Million credits per hour for me. The modified version I currently use is pulling in an average of 220 to 250 Million credits per hour, and I think I can increase that another 10-20+ Percent with some more optimization. I’ve also eliminated the Hang-Causing Bugs present in the original and added some additional functionality.
To be safe, the script tried to destroy sector fighters on entering, and then places it’s own. I could use a Sector Array fig list to track existing Fighters and only attack and place figs if necessary (More efficient), but the script could not update that fig list if a Fig was destroyed in mid-execution. If only attacking unfigged sectors, it would hang if it entered a sector where my fig had been destroyed and replaced with another. This lead to the search for a system-wide figlist, and my first post above when I finally found a solution. ;)
===
The only Scripting question I can think of at the moment that I haven’t found a good solution to (though I haven’t researched it that much yet) is randomizing the order of an array. Breadth type searches that I have seen get a list of Adjacent Sector Numbers in order from lowest to highest, or highest to lowest. This makes it possible, when running a fig surround script for example, to anticipate the sector where the Script will hit next.
What I want to do is get a list of sectors adjacent to a specified sector, and then randomize that list for Script handling. For example, in Sector one, it would return 1=2 2=3 3=4 4=5 5=6 6=7. What I want is to take that list and randomize it. For example, set: 1=4 2=3 3=6 4=2 5=7 6=5, and then while-loop through the sectors in the new random order. Combine that with an unfigged breadth type search that has a constant 35-65% chance to skip the next closest unfigged sector, and a Planet Grid script like the one I wrote would be nearly impossible to anticipate or counter.
I haven’t done a lot of research into randoms in TWX yet, so what I want to do might be relatively easy, or impossible. This will be the next problem I tackle though, after I re-optimize some parts of my other scripts with info I've learned today.
If I can’t do it through a truly random method, I will probably just set up a bunch of pre-defined ‘random’ order configurations and use a random number to pick the sector configuration I will use to set the adjacent sector list to for each step. For Example Config 1 would set 1=4, 2=5 3=2 4=7 5=6 6=3. then Config 2 would set 1=6 2=7 3=4 4=2 5=3 6=5, etc etc etc. Not truly random, but it accomplishes a similar effect.
I’ll definitely post any future questions I have. You guys have quite a lot more experience than me, and something that would take me a few days to figure out has probably already been solved somewhere (and even better than what I was trying to do, like the above script) ;)
Thanks for your help,
-Dark Jester
 


Thu May 31, 2007 5:51 am
Profile
Veteran Op
User avatar

Joined: Thu Jun 02, 2005 2:00 am
Posts: 5558
Location: USA
Unread post 
*nod* Tsst is a script that was released as a beta, there's a lot of improvments to be made. But killing and laying figs is probably not one of them. In an aggressive game your fig grid will be gridded over and parm triggers won't always catch them if you're in the middle of a macro loop. You can simply do....
"m 1234 * n n * z a 99999 * f z 1 * z c d r * "

Which, as a macro, is pretty dang fast despite the scroll. Will not hang on mines, cannons, will retreat off high fig amounts, and will work regardless of whether the sector has been gridded or not.

The trick to improving tsst is to reduce the number of moves you make. The BFS can work, but can be very slow if you don't have a full ZTM to start. If, however, do you have one... it's the fastest way to find a good port. So check for the amount of warps you have when you start the script (or any number of other ways) and then select based on that.

Another simple improvement is to use short mows instead of complete mows. It's port explore routine is to pick a random sector and mow out there to it and see if it finds anything. That can send you 30+ hops away and out of xport range. So trim the mow at, say, 7 hops and smart holo as you go.

Still, you better be sure the uni is safe before doing stuff like that. It's all too easy to get killed that way. Safeties were the first thing I added to tsst.

A surround script is still very predictable, whether you randomize it or not. Think about a 4 way, you have 1 fig adj and the enemy has 3 figs. You hit 2 figs, in whatever order, and they're going to know you're doing surrounds, they'll have your timing and they'll know exactly what sector you're going to hit. In a game where the competition is sloppy you won't have to worry about any of that, but in game where it isn't... surrounds will get you killed, random or not.

Randomizer algos are a bit messy, but I use a simple shuffle on stuff like this. getRnd between 1 and 2, if it's 1 do nothing, if it's 2 swap the order. Either way move down the list, repeat. Make multiple passes. Done. This isn't truely random, no computer random is ever truely random... but it's psuedo random enough that an attacker won't guess the output by itself. Altho as the grid layout changes you might find that some areas have a higher chance of being predicted.

_________________
May the unholy fires of corbomite ignite deep within the depths of your soul...

1. TWGS server @ twgs.navhaz.com
2. The NavHaz Junction - Tradewars 2002 Scripts, Resources and Downloads
3. Open IRC chat @ irc.freenode.net:6667 #twchan
4. Parrothead wrote: Jesus wouldn't Subspace Crawl.

*** SG memorial donations via paypal to: dpocky68@booinc.com
Image


Thu May 31, 2007 3:21 pm
Profile ICQ WWW
Gameop

Joined: Thu Apr 19, 2007 2:10 am
Posts: 5
Unread post 
Been playing with getNearestWarps and getCourse. These completely rock!
Thanks for pointing them out to me Sing. These are definately more efficient than the full breadth search structures and course plotters I was using before.


Fri Jun 01, 2007 4:50 am
Profile
Veteran Op
User avatar

Joined: Thu Jun 02, 2005 2:00 am
Posts: 5558
Location: USA
Unread post 
Quote:
Anyway, I figured it would be faster to only attack when necessary. You mentioned that Parm triggers won't always work if they happen in the middle of a macro loop. Is this because the display may be aborted, or the trigger just won't fire if TWX is processing another command?


I'm not exactly sure why, but I've had a lot of different things happen. I've had packets dropped, had text aborted, had triggers just not fire, and timing get all wonky, my CPU load can sometimes get jacked pretty high during a tsst run.

It all comes down to this tho... it may be a little faster not to deal w/ all that scroll, but if it messed up even once you'll get hung on a fig. If nobody is around to kill you, then you're just hung till you fix it. If someone is around... you're dead meat. Do you want to risk your cash and game for such a little gain? That's why I tend to script for safety first.

Quote:
My main optimisation areas have been around the way it locates ports. After having the original script pick a random sector and run me into other players' home base sectors a couple times and just hang, I decided to re-do it.


Yes, it's a mess for sure. If you have a ztm it's very easy to do a nice, fast, smart tsst. But turboSST was designed to run w/o a ztm, in early game unlims... like the first hour or 2 of the game. Because of that, xide used a mowing explore routine and a "throw it at the wall and hope it sticks" port finder.

Amazingly it performs pretty well, but the lower your ship's xport range the longer you'll spend positioning ships. Positioning also takes place early on in the cycle, as the script runs it has to do less of this. The trick is writing a script that works in the best of both worlds. There are a few of us that have such scripts, but they're kept under a tight lid most of the time.

Increasing your furb % is a good idea as the game progresses. Ideally it'd be a variable from the menu. Early on in the game when your exp isn't stealing full holds your runs to terra are very risky. I tend to use 80% or 90% as my ratio, I find I burn less time furbing and still manage to get good runs. I think tsst's default is like 60% or 70% or something, that's pretty low. Fortunately in an unlim like that xp is pretty much free, it's the risk of getting on a good run when you're understealing that stinks the most. And that happens a lot, sadly.

When comparing runs it's important to factor out ping and server load. I've used the same script once and got 200m an hour, then afew hours later on the same server found that the CPU load was dragging me down to 50m. Locally I tested a cash script and was bringing in over 500m an hour, tested it remotely and was down to 200m. So... make sure your tests even stuff like that out if you want reliable results.

But ya, the bfs commands are super sweet. And I suspect EP's going to make em even sweeter.

_________________
May the unholy fires of corbomite ignite deep within the depths of your soul...

1. TWGS server @ twgs.navhaz.com
2. The NavHaz Junction - Tradewars 2002 Scripts, Resources and Downloads
3. Open IRC chat @ irc.freenode.net:6667 #twchan
4. Parrothead wrote: Jesus wouldn't Subspace Crawl.

*** SG memorial donations via paypal to: dpocky68@booinc.com
Image


Fri Jun 01, 2007 6:50 am
Profile ICQ WWW
Display posts from previous:  Sort by  
Reply to topic   [ 9 posts ] 

Who is online

Users browsing this forum: No registered users and 23 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by wSTSoftware.