PDA

View Full Version : Introduction / my efforts



isomage
12-03-2008, 06:58 AM
Hi all,

This is my first post here.

My main interest is random/procedural generation of maps for roleplaying games. So far, I've written some programs to generate classic-style D&D cave and wilderness maps and Traveller subsector maps; these can be used online here (http://axiscity.hexamon.net/users/isomage/) (note that the cave and wilderness maps tend to look better at larger sizes).

They're nothing like the maps made by some of the wonderful artists here, but feedback is most welcome anyway :)

Steel General
12-03-2008, 07:59 AM
Welcome Aboard!

Redrobes
12-03-2008, 08:01 AM
Those map generators are really excellent. I ran the cave one many times and it gave great results every time. If I were programming that I would randomize a height map and then just slice it through the middle but that would give blobs. Yours seem well connected with nice chutes and passages.

The traveller one is cool too. Two seconds and you have an entry for last months space map contest. I was looking for a planet name creator only last month to try to make them with. I just stole arabic nouns in the end but your planets have good names. The most impressive thing is that you output in PDF. Do you use a converter like GhostScript or do you draw in postscript directly.

The only suggestion I would say is to have a checkbox for not having a grid on the cave generator. Many people import these things into stuff and play with them from there - like texture them etc, before making them a final map. RobA has a great Gimp script around here that converts black and white into dungeon textured map.

Robs script
http://www.cartographersguild.com/showthread.php?t=2759

jezelf
12-03-2008, 08:47 AM
welcome. yeah I had a play about with the cave one too.great stuff!

isomage
12-03-2008, 05:24 PM
welcome. yeah I had a play about with the cave one too.great stuff!


Those map generators are really excellent.


Welcome Aboard!

Thanks :)



I was looking for a planet name creator only last month to try to make them with. I just stole arabic nouns in the end but your planets have good names.

I was initially playing around with Markov chains (see, for example, here (http://www.cs.bell-labs.com/cm/cs/pearls/sec153.html)), seeding them with Latin or Greek names or real star names, but I wasn't very happy with the results. In the end I just reimplemented the planet name generator from Elite (http://en.wikipedia.org/wiki/Elite_(video_game)) (there's source code floating around on the web somewhere).


The most impressive thing is that you output in PDF. Do you use a converter like GhostScript or do you draw in postscript directly.

It generates PostScript which is then filtered through GhostScript to produce the PDF.


The only suggestion I would say is to have a checkbox for not having a grid on the cave generator.

Done!

RobA
12-03-2008, 10:51 PM
@isomage -

Really sweet!

I took one of your the random caves (now without grids ;) ) and scaled it 200% then ran my "dungeon map prettier" script in gimp that Redrobes mentioned.

8169

Are you using a random walk algorithm to generate the caves?

-Rob A>

isomage
12-03-2008, 11:08 PM
I took one of your the random caves (now without grids ;) ) and scaled it 200% then ran my "dungeon map prettier" script in gimp that Redrobes mentioned.

That looks awesome :)


Are you using a random walk algorithm to generate the caves?

Yep. Random walks for the caves, fractal height fields for the hex maps, and by-the-book rules (Little Black Book 3, Worlds and Adventures) for the Traveller subsectors.

Redrobes
12-04-2008, 07:04 AM
...I just reimplemented the planet name generator from Elite (http://en.wikipedia.org/wiki/Elite_%28video_game%29) (there's source code floating around on the web somewhere).Dang, I searched for that and mentioned it in my thread but I couldn't find the code. I remember it being cool so no wonder your names were pretty good. Now I know its out there ill try again. Wikipedia mentioned it but didnt have any link to it.


It generates PostScript which is then filtered through GhostScript to produce the PDF.I had a friend once that used to program in postscript on the printer - as in use the printers CPU to generate patterns, fractal and other itterative ones, which it then printed. So you must be running your cgi script as a full exe not a perl/PHP thing then unless there is some nice interface to Ghostscript from a script. I am pretty sure I could not do that with my web provider as they only install a certain limited set of perl modules. Well, if your able to tell us more about the process that would be interesting. I thought it was quite impressive - what you have done is a bit harder than people might realize.


Done!Cool and I see Robs already provided the demo :) I reckon that your page will see a lot of use with Robs script too.

Midgardsormr
12-04-2008, 12:09 PM
Dang, I searched for that and mentioned it in my thread but I couldn't find the code. I remember it being cool so no wonder your names were pretty good. Now I know its out there ill try again. Wikipedia mentioned it but didnt have any link to it.

http://www.iancgbell.clara.net/elite/bbc/index.htm#src

ravells
12-04-2008, 02:21 PM
This is superb stuff. I love the way that the images produced by Iso's maps are perfect to be run on RobA's script.

Welcome to the Guild, Iso - the traveller maps really rock!

Redrobes
12-04-2008, 04:17 PM
http://www.iancgbell.clara.net/elite/bbc/index.htm#srcThats cool Mid but I cant see any clear sources for that name generator. Its hidden in the assembly of the main game I think and that requires considerable effort to decode - to the point that he mentions that one guy has done it and recoded it and how hard it was. What I am hoping to find is a name generator in any modern language like 'C' or something like that. Maybe its not possible without all the game code too as a means of hashing up the name.

This is the closest I have but even this one reckons that its not the original code for it.

http://www.parallelrealities.co.uk/projects/randomNameGen.php

Maybe its impossible to get the original generator any more. Isomage - do you think you have the original Elite name generator or something approximately like it.

isomage
12-04-2008, 04:43 PM
Ian Bell has released C source code for a text-version of Elite, and it contains the name generator: http://www.iancgbell.clara.net/elite/text/

I think I might have worked from Christian Pinder's reverse-engineered C code, which doesn't seem to be available from that site anymore.

Here's my Python version. If you set ELITE = True, successive calls to name() will generate the sequence of names used in the game -- look for Lave on call 7 (starting from 0); otherwise you'll get a random sequence.



ELITE = False

if ELITE:
seed = [0x5A4A, 0x0248, 0xB753]
else:
import random
seed = [random.randint(0, 0xffff), random.randint(0, 0xffff), random.randint(0, 0xffff)]

def tweakseed():
temp = (seed[0] + seed[1] + seed[2]) % 0x10000
seed[0] = seed[1]
seed[1] = seed[2]
seed[2] = temp

digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetied orquanteisrion"

def name():
longnameflag = seed[0] & 0x40

name = ""

for n in range(4):
d = ((seed[2] >> 8) & 0x1f) << 1

tweakseed()

if n < 3 or longnameflag:
name += digraphs[d:d+2]

return name.replace(".", "").title()

isomage
12-04-2008, 04:48 PM
So you must be running your cgi script as a full exe not a perl/PHP thing then unless there is some nice interface to Ghostscript from a script.

I did it in Python, but the basic idea would be the same in PERL: open a pipe to the system's GhostScript converter and write your generated PostScript code to it like a file.

Redrobes
12-04-2008, 04:54 PM
Wow that's excellent and totally rep worthy if I haven't already. I actually remember 'Lave' too. I think I might just try this to see what the names were and if I remember any more. Did you see all of our November challenge entries ? I think mine would have been improved with better names. Although our stars are named with Arabic, for some reason I think the ones in the sky sounded better than the ones I had used.

Redrobes
12-04-2008, 05:02 PM
I did it in Python, but the basic idea would be the same in PERL: open a pipe to the system's GhostScript converter and write your generated PostScript code to it like a file.Very good. I don't think I am able to do that tho. I use an external web space provider which gives certain access rights. I don't think I can run GhostScript on their server in the cgi-bin area. Still, if your able, then thats a really excellent thing to do.

I am gonna go and see if I can Perl up your python Elite code. :)

isomage
12-04-2008, 05:34 PM
I am gonna go and see if I can Perl up your python Elite code. :)



my $ELITE = 1; # Set to 1 for Elite names, other for random names

my @seed = ($ELITE == 1) ? (0x5A4A, 0x0248, 0xB753)
: (int(rand(0xffff)), int(rand(0xffff)), int(rand(0xffff)));

sub tweakseed() {
push @seed, ($seed[0] + $seed[1] + $seed[2]) % 0x10000;
shift @seed;
}

my $digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetied orquanteisrion";

sub name() {
my $longnameflag = $seed[0] & 0x40;

my $name = "";

foreach my $n (0 .. 3) {
my $d = (($seed[2] >> 8) & 0x1f) << 1;

tweakseed();

if ($n < 3 || $longnameflag) {
$name .= substr($digraphs, $d, 2);
}
}

$name =~ s/\.//g;

$name =~ s/^(.)/\U$1/;

return $name;
}

Redrobes
12-04-2008, 05:38 PM
Hah ! Just done mine too...



my $elite = 1;

my @seed;
my $digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetied orquanteisrion";

if( $elite )
{
$seed[0] = 0x5A4A;
$seed[1] = 0x0248;
$seed[2] = 0xB753;
}
else
{
$seed[0] = rand() & 0xFFFF;
$seed[1] = rand() & 0xFFFF;
$seed[2] = rand() & 0xFFFF;
}

sub tweakseed()
{
my $temp = ($seed[0] + $seed[1] + $seed[2]) & 0xFFFF;
$seed[0] = $seed[1];
$seed[1] = $seed[2];
$seed[2] = $temp;
}

sub name()
{
my $longnameflag = $seed[0] & 0x40;
my $name = "";

for( $n=0; $n<4; $n++ )
{
my $d = (($seed[2] >> 8) & 0x1f) << 1;
tweakseed();

if( $n < 3 || $longnameflag )
{
$name .= substr( $digraphs, $d, 2 );
}
}

$name =~ s/\.//g;
return $name;
}

print name()."\n";
print name()."\n";
print name()."\n";
print name()."\n";


Lets compare ! :D

Redrobes
12-04-2008, 05:42 PM
I can tell your a better Perl programmer than I.

isomage
12-04-2008, 05:44 PM
I can tell your a better Perl programmer than I.

The code's pretty similar -- I just took a couple of shortcuts. If it works it works! :)

For testing, the first eight names generated in Elite mode should be:

Tibedied
Qube
Leleer
Biarge
Xequerin
Tiraor
Rabedira
Lave

Redrobes
12-04-2008, 07:25 PM
I have plumbed it into my Nov08 challenge star map drawing script. Shame I didn't have this a month ago. Its great that you have given it out now tho.

Should be the first 50 Elite names now with Lave over on the right.

isomage
12-04-2008, 07:43 PM
Nice :)

RobA
12-04-2008, 07:45 PM
OK - I want to play too..

Here it is in php:


#!/usr/bin/php -q
<?php
$elite = TRUE;

if ($elite)
$seed = array(0x5A4A, 0x0248, 0xB753);
else
$seed = array(rand(0, 0xffff), rand(0, 0xffff), rand(0, 0xffff));

function tweakseed() {
global $seed;
$seed[] = ($seed[0] + $seed[1] + $seed[2]) % 0x10000;
array_shift($seed);
}

function name() {
global $seed;
$digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetied orquanteisrion";
$longnameflag = $seed[0] & 0x40;
$name = "";

for ($n=0; $n<4; $n++) {
$d = (($seed[2] >> 8) & 0x1f) << 1;
tweakseed();

if( $n < 3 || $longnameflag )
$name = $name . substr($digraphs, $d, 2);
}

$name = ucwords(str_replace(".", "", $name))."\n";

return $name;
}

if (isset($argv[1]))
for ($n=0; $n<$argv[1]; $n++)
echo name();
else
echo name();
?>


and the results with elite set as true:

Tibedied
Qube
Leleer
Biarge
Xequerin
Tiraor
Rabedira
Lave


-Rob A>

The Good Doctor
12-04-2008, 10:31 PM
I take it you are looking for a name generator that will interface with your program? Or just a name generator?

NeonKnight
12-04-2008, 11:09 PM
WOW!

Welcome to the Guild!

RPMiller
12-05-2008, 01:46 AM
Great stuff!

Sagenlicht
12-05-2008, 07:24 PM
I took isomage's code and did wrap a GUI around.

Enjoy.

I will make a binary for windows, so you easily can use it without having python and PyGTK installed.


#!/usr/bin/env python

# SNG (Star Name Generator) is based on the ELITE game
# Name Generator code written by isomage
# http://http://axiscity.hexamon.net/users/isomage/
# or http://cartographersguild.com

# GUI by Sagenlicht for easier use
# http://cartographersguild.com

# Version 0.5

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import pygtk
pygtk.require('2.0')
import gtk
import random


class SNG:
def __init__(self, useRandom):
if useRandom:
self.seed = [random.randint(0, 0xffff), random.randint(0, 0xffff), random.randint(0, 0xffff)]
else:
self.seed = [0x5A4A, 0x0248, 0xB753]

def tweakseed(self):
temp = (self.seed[0] + self.seed[1] + self.seed[2]) % 0x10000
self.seed[0] = self.seed[1]
self.seed[1] = self.seed[2]
self.seed[2] = temp

def generate_name(self):
self.digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetied orquanteisrion"
longnameflag = self.seed[0] & 0x40

name = ""

for n in range(4):
d = ((self.seed[2] >> 8) & 0x1f) << 1

self.tweakseed()

if n < 3 or longnameflag:
name += self.digraphs[d:d+2]

return name.replace(".", "").title()

def generate_list(self, namesToGenerate):
nameList = []
for i in xrange(namesToGenerate):
nameList.append(self.generate_name())
return nameList

class GUI:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect( "destroy", self.destroy )
self.window.set_title( "ELITE based Name Generator" )
self.window.set_border_width(5)
self.window.set_size_request(250, 400)
self.window.show()

self.mainBox = gtk.VBox()
self.mainBox.set_border_width(5)
self.mainBox.set_size_request(250, 400)
self.window.add(self.mainBox)
self.mainBox.show()

self.generateFrame = gtk.Frame(label="Names to generate")
self.mainBox.pack_start(self.generateFrame, False, False, 1)
self.generateFrame.set_label_align(0.5, 0.5)
self.generateFrame.show()

self.comboList = gtk.combo_box_new_text()
self.comboList.append_text ("5")
self.comboList.append_text ("10")
self.comboList.append_text ("25")
self.comboList.append_text ("50")
self.comboList.set_active (1)
self.generateFrame.add(self.comboList)
self.comboList.show()

self.modeFrame = gtk.Frame(label="Choose Mode")
self.mainBox.pack_start(self.modeFrame, False, False, 1)
self.modeFrame.set_label_align(0.5, 0.5)
self.modeFrame.show()

self.modeBox = gtk.VBox()
self.modeBox.set_border_width(5)
self.modeBox.set_size_request(200, 60)
self.modeFrame.add(self.modeBox)
self.modeBox.show()

self.randomButton = gtk.RadioButton(None, "Random Star Names")
self.modeBox.pack_start(self.randomButton, False, False, 1)
self.randomButton.show()
self.randomButton.set_active(True)
self.eliteButton = gtk.RadioButton(self.randomButton, "ELITE Game Names")
self.modeBox.pack_start(self.eliteButton, False, False, 1)
self.eliteButton.show()

self.nameFrame = gtk.Frame(label="Generated Names")
self.mainBox.pack_start(self.nameFrame, True, True, 1)
self.nameFrame.set_label_align(0.5, 0.5)
self.nameFrame.show()

self.tmpBox = gtk.VBox()
self.tmpBox.set_border_width(0)
self.tmpBox.set_size_request(180, 200)
self.nameFrame.add(self.tmpBox)
self.tmpBox.show()

scroll_box = gtk.ScrolledWindow()
scroll_box.set_border_width(5)
scroll_box.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC )
self.tmpBox.pack_start( scroll_box, True, True, 0 )
scroll_box.show()

self.namesBox = gtk.TextView(buffer=None)
self.namesBoxBuffer = self.namesBox.get_buffer()
self.namesBox.set_editable(False)
self.namesBox.set_cursor_visible(False)
self.namesBox.set_wrap_mode(gtk.WRAP_WORD)
self.namesBox.set_justification(gtk.JUSTIFY_LEFT)
self.namesBox.show()
scroll_box.add_with_viewport(self.namesBox)

self.buttonBox = gtk.HButtonBox()
self.buttonBox.set_layout(gtk.BUTTONBOX_END)
self.buttonBox.set_spacing(5)
self.buttonBox.set_border_width(1)
self.buttonBox.set_size_request(250, 50)
self.mainBox.pack_start(self.buttonBox, True, True, 1)
self.buttonBox.show()

cancelButton = gtk.Button( stock=gtk.STOCK_CLOSE )
cancelButton.connect_object( "clicked", gtk.Widget.destroy, self.window)
self.buttonBox.add(cancelButton)
cancelButton.show()

okButton = gtk.Button(stock=gtk.STOCK_OK)
okButton.connect("clicked", self.ok_clicked)
self.buttonBox.add(okButton)
okButton.show()

def ok_clicked( self, widget, data = None):
if self.randomButton.get_active():
useRandom = True
if self.eliteButton.get_active():
useRandom = False
generateNames = SNG(useRandom).generate_list(int(self.comboList.ge t_active_text()))
tmpString = ""
heightRequest = 0
for name in generateNames:
tmpString = (tmpString + "%s" % name + "\n")
self.namesBoxBuffer.set_text(tmpString)
heightRequest = heightRequest + 14
self.namesBox.set_size_request(180, heightRequest)

def destroy( self, widget, data=None ):
gtk.main_quit()

def gtkCall(self):
gtk.main()

if __name__ == "__main__":
callSNG = GUI()
callSNG.gtkCall()


EDIT: Added a screenshot of the GUI. Dont get irritated by the german button, thats language depend so no worries :)

isomage
12-05-2008, 07:29 PM
Cool. I've given the name generator its own page on my site too.

Sagenlicht
12-05-2008, 08:17 PM
Hmm just did the windows binary but I cant upload it here, as it is 13 MB compressed as a zip or 7.5 MB as a 7z file.

Anyone knows a place where I can upload it?

Redrobes
12-05-2008, 08:33 PM
13 MB:shock: choke ! Firefox and all its dll's are 13Mb - what have you got in there ?

Sagenlicht
12-05-2008, 08:38 PM
Hmm the python and GTK runtime enviroment :P

I just use the py2exe tool for this. Dunno if it can be optimized I just follow its tutorial for PyGTK scripts.

Anyways I would recommend to just install python, GTK and PyGTK and use the script. Having Python installed never hurts :)

I decided to create a new threat here (http://www.cartographersguild.com/showthread.php?t=3622), so its easier to find the script because I hope some people are interested in it :)

It includes the link to my How-To for the Phyton setup.

Steel General
12-05-2008, 08:51 PM
I know next to nothing about Python, Perl or PhP but I would think you should be able to compile it into a single executable or at the very least a page and a .dll.

Saying that, my only experience is with ASP.NET so I could be way off base. :)

isomage
12-05-2008, 08:55 PM
Here's a comparison of some file hosting services:
http://en.wikipedia.org/wiki/One-click_hosting#One-click_hosting

I can't personally vouch for any of them, but I've seen people using mediafire (http://www.mediafire.com/) and rapidshare (http://rapidshare.com/), both of which are free.

RobA
12-06-2008, 04:44 PM
In case anyone misses it I have updated my map prettier script for gimp to optionally download a random cave from isomage's website as a base image.

Check my sig for the link.

-Rob A>

Sagenlicht
12-07-2008, 06:33 AM
A few days ago, I made an overview over all scripts we made for GIMP here (http://www.cartographersguild.com/showthread.php?t=3531).

If you are using GIMP try them out :)

kensanata
09-11-2009, 11:51 AM
I recently investigated the topic of random name generators, and tried to understand what made the Elite name generator "tick". And I think I've found a way. (From a blog post (http://www.emacswiki.org/alex/2009-09-11_Elite_Names) of mine.)



my $digraphs = "..lexegezacebisousesarmaindire.aeratenberalavetied orquanteisrion";
my $max = length($digraphs);

sub name {
my $length = 5 + rand(5); # 4-8
my $name = '';
while (length($name) < $length) {
$name .= substr($digraphs, 2*int(rand($max/2)), 2);
}
$name =~ s/\.//g;
return $name;
}

for my $n (0..100) {
printf "%3d. %s\n", $n, name();
}


Want a different "sound" for your subsector? Here's an example I tried:



my $digraphs = "fafemalunabararerixevivoine.n.q.pazizozutatetitotu ..";


More variation in name length?



my $length = 4 + rand(7); # 4-8


Cheers
Alex

Sharpe
03-15-2013, 02:04 PM
Is there an updated link for this? Sorry if it was posted somewhere in the thread.