Method for a Random Gateway Builder

This is a moderated forum that collects tutorials, guides, and references for creating Transcendence extensions and scripts.
Post Reply
User avatar
Periculi
Fleet Officer
Fleet Officer
Posts: 1282
Joined: Sat Oct 13, 2007 7:48 pm
Location: Necroposting in a forum near you

(sysAddStarGateTopology nodeID gateID destID gateID) is used to create a link from a new gate to an existing destination gate.

While I am waiting for my download, I will demonstrate a way to add randomly chosen 2-way gate links in a given topology structure.

First of all, I created a blank system element to put the <OnGlobalTopologyCreated> event in. This will be called in the beginning of the game, when the topology has been prepared, before the player enters Eridani.

Code: Select all

<SystemType UNID="&ssTopoMaster;">
  <Events>
      <OnGlobalTopologyCreated>


      </OnGlobalTopologyCreated>
  </Events>
</SystemType>
Inside the tag, a block of script to process the newly created network and make some decisions, then apply them to the topology structure.
First it is time to set up some variables for the process:

Code: Select all

		(block (minBase maxBase sysList gateList rand levelOffsetMax)

		  (setq minBase 5)
		  (setq maxBase 25)
		  (setq levelOffsetMax 3)
		  (setq rand (random minBase maxBase))
		  (dbgLog "Number of Links to be made: " rand)
minBase and maxBase are the spectrum for the number of links to be added to the topology, the result is stored in rand. levelOffsetMax is the maximum above or below the system level of the system being linked.

Next get a list of the systems using filter:

Code: Select all

		  (setq sysList (filter (sysGetNodes) sysID (sysHasAttribute sysID "goodLinks")))
That's a great new feature- sysGetNodes get all the nodes available in the topology connected to rootNodes (decisions for regular nodes not chosen are discarded) and filter gets all the nodeID with an attribute I added to the nodes I wanted to include ("goodLinks"). This allows me to include just the nodes I want to have qualify for a new random link, and not link to nodes like Elysium, Heretic, and Huaramarca.

There is much more that could be done for linking through filters. Say you wanted to have a the nodes divided? Say a set for the origin and a set for the destination. You could simply produce two lists in this manner, with the attribute in the nodeID to distinguish them.

Next it is time to start making some links. 'rand' was created to define the number of links to be made, so now the link process will simply repeat that many times in a (for:

Code: Select all


		  (for i 1 rand
			(block (linkA offSet linkB gatesA gateNameA gatesB gateNameB levelA gateSeed)
			  (setq linkA (random sysList))
			  (setq levelA (sysGetLevel linkA))
			  (setq offSet (random 0 levelOffSetMax))
In the first part of the linking block a random nodeID is selected from sysList as linkA, and the level of that node is found as levelA, then a number for the levels off set in either direction from levelA is created as offSet. levelOffSetMax was defined in the first portion of the script, but each link offSet is chosen randomly from 0 (only same level) to the max allowed. In this example that amount was defined as 3 so the offSet becomes (levelA +0 to levelA -0) through (levelA +3 to levelA - 3).


Next the destination is chosen, which refers to another function to return it.

Code: Select all


			  (setq linkB (topoGetTargetFiltered sysList linkA levelA offSet))
Refer to the code for that function further below in this post. It returns a nodeID for the destination, and the process moves on.

In the next step a count of the gates is found for each system to help uniquely name the gate to be created and the names for the gates are made. The destination node uses an existing gate in gateSeed, so the destination node must have at least one gate. After the names are made, the stargate links are added.

Code: Select all

			  (setq gatesA (count (sysGetStargates linkA)))
			  (setq gatesB (count (sysGetStarGates linkB)))
			  (setq gateSeed (item (sysGetStargates linkB) 0))
			  (setq gateNameA (cat "RandGate" gatesA))
			  (setq gateNameB (cat "RandGate" gatesB))
			  (sysAddStargateTopology linkA gateNameA linkB gateSeed)
			  (sysAddStargateTopology linkB gateNameB linkA gateNameA)

			  ;(dbgLog "used Seed: " gateSeed)
			  ;(dbgLog (cat linkA " added " gateNameA " linked " linkB " with gate " gateNameB))
			  

			)
		  );end main iteration

Notice that the gate pair isn't correct yet. gateA is pointed to an existing gate in the destination, and gateB is pointed to gateA- the pairs don't match up. But I found that when you create the stargate in the system, in most cases you can return the proper gate name to attach to the stargate by searching the destination for a matching link and thus get sent to the right gate. In a stargate placement script I wrote, the gates that got built were correct when travelling, even in the instance of a [prev] in the mix to another system (although why these types of loops don't break.. well, must be something to do with the topology being processed first.)

Code: Select all


(dbgLog "Sucessfully Completed Randomizing.")

		)

Next. it's time to look at the <Globals> that help this function get a good linkB for the destination:

Code: Select all

  (setq topoGetTargetFiltered (lambda (sysList linkA levelA offSet)
	(block (targetList target)
		;start building the targetList
		(setq targetList (filter sysList sysID (eq (sysGetLevel sysID) levelA)))
		(if (geq offSet 1) 
		  (block nil
			(setq targetList (filter sysList sysID (leq (sysGetLevel sysID) (add levelA offSet))))
			(setq targetList (filter targetList sysID (geq (sysGetLevel sysID) (subtract levelA offSet))))

			(dbgLog (count targetList) " nodes targetted")			
		  )
		);end if

	(setq target (topoPickATarget targetList linkA))
	
	)
  ))
targetList is created using the level offset to filter the available nodeID to create the link to.

Here is the quick filter for the actual nodeID now that the targetList is ready:

Code: Select all


  (setq topoPickATarget (lambda (targetList linkA)
	(block (linkID)

	(setq linkID (random targetList))
	(if (eq linkID linkA)
	(setq linkID (topoPickATarget targetList linkA))
	)

	linkID
	)
  ))
Just a simple filter to prevent linkA and linkB from matching, because that produces gates that don't work.

The grand result of those two little functions is to return a single nodeID that becomes the destination in linkB of the event block.

When applied to a linear topology, this can produce an interwoven network by adding extra links that create loops.

When applied to a topology that is built from segments with loops and complex networks the results can be very interesting.

One really cool effect was to tie together smaller rootNode anchored sections by adjusting the script to target a different set of attributes between each link, and assinging those to the segments- in addition to the level, a check for the attributes was made and the target list filtered to create a bridge between two independent network areas.

Any ideas on improving this script? Questions?
Last edited by Periculi on Sun Sep 07, 2008 11:25 pm, edited 1 time in total.
User avatar
Mutos
Militia Lieutenant
Militia Lieutenant
Posts: 218
Joined: Thu Aug 14, 2008 3:31 am
Location: Near Paris, France
Contact:

Hi Periculi,


That seems to be very interesting to create large random topologies with a controlled set of features. I like the idea to have random blocks with pre-defined bridges between them. For my part I'll not use it because my topology is static, but this could make great universes...

Indeed Transcendence has gained one more level in flexibility with that script !
@+

Benoît 'Mutos' ROBIN
Hoshikaze 2250 Project
Post Reply