r1969 - in branches/nexuiz-2.0/data: . qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Dec 3 06:49:07 EST 2006


Author: div0
Date: 2006-12-03 06:49:06 -0500 (Sun, 03 Dec 2006)
New Revision: 1969

Modified:
   branches/nexuiz-2.0/data/default.cfg
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
Log:
new maplist code, g_maplist_shuffle, g_maplist_selectrandom hereby deprecated


Modified: branches/nexuiz-2.0/data/default.cfg
===================================================================
--- branches/nexuiz-2.0/data/default.cfg	2006-12-03 11:47:47 UTC (rev 1968)
+++ branches/nexuiz-2.0/data/default.cfg	2006-12-03 11:49:06 UTC (rev 1969)
@@ -198,7 +198,8 @@
 set g_maplist_defaultlist "'dm_aggressor''dm_aneurysm''dm_basement''dm_bleach''dm_bluesky''dm_bloodprison''dm_darkzone''dm_downer''dm_evilspace''dm_farewell''dm_runningman''dm_runningman_1on1remix''dm_silvercity''dm_skyway''dm_slimepit''dm_soylent''dm_starship''dm_stormkeep''dm_toxic''dm_warfare''dom_aggressor''dom_aneurysm''dom_basement''dom_bleach''dom_darkzone''dom_downer''dom_evilspace''dom_runningman''dom_runningman_1on1remix''dom_silvercity''dom_skyway''dom_slimepit''dom_soylent''dom_starship''dom_stormkeep''dom_toxic''lms_aggressor''lms_basement''lms_bleach''lms_bluesky''lms_bloodprison''lms_downer''lms_evilspace''lms_farewell''lms_runningman''lms_runningman_1on1remix''lms_skyway''lms_slimepit''lms_soylent''lms_starship''lms_stormkeep''lms_toxic''lms_warfare''rune_aggressor''rune_aneurysm''rune_basement''rune_bleach''rune_darkzone''rune_downer''rune_evilspace''rune_runningman''rune_runningman_1on1remix''rune_silvercity''rune_skyway''rune_slimepit''rune_soylent''rune_starship''rune_stormkeep''rune_toxic''tdm_aggressor''tdm_aneurysm''tdm_basement''tdm_bleach''tdm_darkzone''tdm_downer''tdm_evilspace''tdm_farewell''tdm_runningman''tdm_runningman_1on1remix''tdm_silvercity''tdm_skyway''tdm_slimepit''tdm_soylent''tdm_starship''tdm_stormkeep''tdm_toxic''tdm_warfare'"
 seta g_maplist $g_maplist_defaultlist
 seta g_maplist_index 0 // this is used internally for saving position in maplist cycle
-seta g_maplist_selectrandom 0 // if 1, a random map will be chosen as next map
+seta g_maplist_selectrandom 0 // if 1, a random map will be chosen as next map; DEPRECATED in favor of g_maplist_shuffle
+seta g_maplist_shuffle 0 // new randomization method: like selectrandom, but avoid playing the same maps in short succession. This works by taking out the first element and inserting it into g_maplist with a bias to the end of the list.
 // timeout for kill credit when your damage knocks someone into a death trap
 set g_maxpushtime 8.0
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2006-12-03 11:47:47 UTC (rev 1968)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2006-12-03 11:49:06 UTC (rev 1969)
@@ -392,29 +392,19 @@
 	return strcat("dm_", mapname);
 }
 
+float Map_Count, Map_Current;
+
+// NOTE: this now expects the map list to be already tokenize()d and the count in Map_Count
 float GetMaplistPosition()
 {
-	float pos, f;
-	string map, s;
+	float pos;
+	string map;
 
-	map = strzone(GetMapname());
-	pos = 0;
-	f = tokenize(cvar_string("g_maplist"));
-
-	while(pos < f)
-	{
-		s = strzone(argv(pos));
-		if(s == map)
-		{
-			strunzone(s);
-			strunzone(map);
+	map = GetMapname();
+	for(pos = 0; pos < Map_Count; ++pos)
+		if(map == argv(pos))
 			return pos;
-		}
-		strunzone(s);
-		pos++;
-	}
 
-	strunzone(map);
 	// resume normal maplist rotation if current map is not in g_maplist
 	return cvar("g_maplist_index");
 }
@@ -449,6 +439,131 @@
 	return TRUE;
 }
 
+string Map_Filename(float position)
+{
+	return strcat("maps/", argv(position), ".mapcfg");
+}
+
+float(float position, float pass) Map_Check =
+{
+	string filename;
+	filename = Map_Filename(position);
+	if(TryFile(filename))
+	{
+		if(pass == 2)
+			return 1;
+		if(MapHasRightSize(argv(position)))
+			return 1;
+		return 0;
+	}
+	else
+		dprint( "Couldn't find '", filename, "'..\n" );
+
+	return 0;
+}
+
+void(float position) Map_Goto =
+{
+	cvar_set("g_maplist_index", ftos(position));
+	localcmd(strcat("exec \"", Map_Filename(position) ,"\"\n"));
+}
+
+// return codes of map selectors:
+//   -1 = temporary failure (that is, try some method that is guaranteed to succeed)
+//   -2 = permanent failure
+float() MaplistMethod_Iterate = // usual method
+{
+	float pass, i;
+
+	for(pass = 1; pass <= 2; ++pass)
+	{
+		for(i = 1; i < Map_Count; ++i)
+		{
+			float mapindex;
+			mapindex = math_mod(i + Map_Current, Map_Count);
+			if(Map_Check(mapindex, pass))
+				return mapindex;
+		}
+	}
+	return -1;
+}
+
+float() MaplistMethod_Repeat = // fallback method
+{
+	if(Map_Check(Map_Current, 2))
+		return Map_Current;
+	return -2;
+}
+
+float() MaplistMethod_Random = // random map selection
+{
+	float i, imax;
+
+	imax = 42;
+
+	for(i = 0; i <= imax; ++i)
+	{
+		float mapindex;
+		mapindex = math_mod(Map_Current + ceil(random() * (Map_Count - 1)), Map_Count); // any OTHER map
+		if(Map_Check(mapindex, 1))
+			return mapindex;
+	}
+	return -1;
+}
+
+float(float exponent) MaplistMethod_Shuffle = // more clever shuffling
+// the exponent sets a bias on the map selection:
+// the higher the exponent, the 
+{
+	float i, j, imax, insertpos;
+
+	imax = 42;
+
+	for(i = 0; i <= imax; ++i)
+	{
+		string newlist;
+
+		// now reinsert this at another position
+		insertpos = pow(Map_Count, exponent);
+		insertpos = random() * insertpos;              // ]0, (Map_Count)^exponent]
+		insertpos = pow(insertpos, 1 / exponent);      // ]0, Map_Count]
+		insertpos = ceil(insertpos);                   // {1, 2, 3, ..., Map_Count}
+		dprint("SHUFFLE: insert pos = ", ftos(insertpos), "\n");
+
+		// insert the current map there
+		newlist = "";
+		for(j = 1; j < insertpos; ++j)                 // i == 1: no loop, will be inserted as first
+			newlist = strcat(newlist, "'", argv(j), "'");
+		newlist = strcat(newlist, "'", argv(0), "'");  // now insert the just selected map
+		for(j = insertpos; j < Map_Count; ++j)         // i == Map_Count: no loop, has just been inserted as last
+			newlist = strcat(newlist, "'", argv(j), "'");
+		cvar_set("g_maplist", newlist);
+		Map_Count = tokenize(newlist);
+
+		// NOTE: the selected map has just been inserted at (insertpos-1)th position
+		Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
+		if(Map_Check(Map_Current, 1))
+			return Map_Current;
+	}
+	return -1;
+}
+
+void() Maplist_Init =
+{
+	string temp;
+	temp = cvar_string("g_maplist");
+	Map_Count = tokenize(temp);
+	if(Map_Count == 0)
+	{
+		bprint( "Maplist is empty!  Resetting it to default map list.\n" );
+		cvar_set("g_maplist", temp = cvar_string("g_maplist_defaultlist"));
+		Map_Count = tokenize(temp);
+	}
+	if(Map_Count == 0)
+		error("empty maplist, cannot select a new map");
+	Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
+}
+
 void() GotoNextMap =
 {
 	//local string nextmap;
@@ -490,164 +605,53 @@
 	}
 	else
 	{
-		// method 0
-		local float lCurrent;
-		local float lSize;
-		local float lOldCurrent;
-		local float lBeforeCurrent;
-		local float pass;
-		local float found_but_wrong_size;
-		found_but_wrong_size = FALSE;
+		float nextMap;
+		float allowReset;
 
+		// cvar "nextmap" always gets priority
 		if(TryFile(strcat("maps/", cvar_string("nextmap"), ".mapcfg")))
 		{
 			localcmd(strcat("exec \"maps/", cvar_string("nextmap"), ".mapcfg\"\n"));
 			return;
 		}
 
-		pass = 0;
-		while (pass < 2)
+		for(allowReset = 1; allowReset >= 0; --allowReset)
 		{
-			pass = pass + 1;
-			local string temp;
-			temp = cvar_string( "g_maplist" );
-			if(temp == "")
-			{
-				bprint( "Maplist is empty!  Resetting it to default map list.\n" );
-				cvar_set("g_maplist", cvar_string("g_maplist_defaultlist"));
-				temp = cvar_string( "g_maplist" );
-			}
-			temp = strzone(temp);
-			dprint("g_maplist is ", temp, "\n");
-			lSize = tokenize( temp );
-			lCurrent = GetMaplistPosition();
-			lCurrent = max(0, min(floor(lCurrent), lSize - 1));
-			lOldCurrent = lCurrent;
-			dprint(ftos(lOldCurrent), " / ", ftos(lSize), " (start)\n");
+			Maplist_Init();
+			nextMap = -1;
 
-			// if we want a random map selection...
-			if(cvar("g_maplist_selectrandom") && lSize > 1)
-			{
-				lBeforeCurrent = lCurrent - 1;
-				if(lBeforeCurrent < 0)
-					lBeforeCurrent = lSize - 1;
-				lCurrent = ceil(random() * (lSize - 1)) - 1; // random in 0..lsize-2
-				if(lCurrent >= lBeforeCurrent)
-					lCurrent += 1;
-				// choose any map except for the current one
-			}
+			if(nextMap == -1)
+				if(cvar("g_maplist_shuffle") > 0)
+					nextMap = MaplistMethod_Shuffle(cvar("g_maplist_shuffle") + 1);
 
-			while( 1 ) {
-				local string lFilename;
+			if(nextMap == -1)
+				if(cvar("g_maplist_selectrandom"))
+					nextMap = MaplistMethod_Random();
 
-				lCurrent = lCurrent + 1;
-				dprint(ftos(lCurrent), " / ", ftos(lSize), "\n");
-				if( lCurrent >= lSize ) {
-					lCurrent = 0;
-				}
-				if( lOldCurrent == lCurrent ) {
-					// we couldn't find a valid map at all
-					if (pass == 1)
-					{
-						if(!found_but_wrong_size)
-						{
-							bprint( "Maplist is bad/messed up. Not one good mapcfg can be found in it!  Resetting it to default map list.\n" );
-							cvar_set("g_maplist", cvar_string("g_maplist_defaultlist"));
-							// let the loop restart with the default list now
-						}
-						else
-						{
-							dprint("wrong size, now trying all\n");
-						}
-					}
-					else
-					{
-						bprint( "Both g_maplist and g_maplist_defaultlist are messed up!  Complain to developers!\n" );
-						localcmd( "disconnect\n" );
-					}
-					break;
-				}
+			if(nextMap == -1)
+				nextMap = MaplistMethod_Iterate();
 
-				lFilename = strzone(strcat( "maps/", argv( lCurrent ), ".mapcfg" ));
-				if( TryFile( lFilename ) ) {
-					if((pass == 2) || MapHasRightSize(argv(lCurrent)))
-					{
-						cvar_set( "g_maplist_index", ftos( lCurrent ) );
-						localcmd(strcat("exec \"", lFilename ,"\"\n"));
-						strunzone(lFilename);
-						pass = 2; // exit the outer loop
-						break;
-					}
-					else
-						found_but_wrong_size = TRUE;
-				} else {
-					dprint( "Couldn't find '", lFilename, "'..\n" );
-				}
-				strunzone(lFilename);
-				//changelevel( argv( lCurrent ) );
-			}
-			strunzone(temp);
-		}
+			if(nextMap == -1)
+				nextMap = MaplistMethod_Repeat();
 
-		/*
-		// method 1
-
-		//local entity pos;
-		local float fh;
-		local string line;
-
-		// restart current map if no cycle is found
-		nextmap = strzone(mapname);
-		fh = fopen("maplist.cfg", FILE_READ);
-		if (fh >= 0)
-		{
-			while (1)
+			if(nextMap >= 0)
 			{
-				line = fgets(fh);
-				if (nextmap == mapname)
+				Map_Goto(nextMap);
+				break;
+			}
+			else // PERMANENT FAILURE
+			{
+				if(allowReset)
 				{
-					strunzone(nextmap);
-					nextmap = strzone(line);
+					bprint( "Maplist contains no single playable map!  Resetting it to default map list.\n" );
+					cvar_set("g_maplist", cvar_string("g_maplist_defaultlist"));
 				}
-				if (!line)
-					break;
-				if (line == mapname)
+				else
 				{
-					line = fgets(fh);
-					if (!line)
-						break;
-					strunzone(nextmap);
-					nextmap = strzone(line);
-					break;
+					error("Everything is broken - not even the default map list works. Please report this to the developers.");
 				}
 			}
-			fclose(fh);
 		}
-		changelevel (nextmap);
-		strunzone(nextmap);*/
-
-		// method 3
-		/*
-		s = cvar_string("g_maplist");
-		nummaps = tokenize(s);
-		// if no map list, restart current one
-		nextmap = mapname;
-		if (nummaps >= 1)
-		{
-			n = 0;
-			while (n < nummaps)
-			{
-				if (argv(n) == mapname)
-					break;
-				n = n + 1;
-			}
-			n = n + 1;
-			if (n >= nummaps)
-				n = 0;
-			nextmap = argv(n);
-		}
-		changelevel (nextmap);
-		*/
 	}
 };
 
@@ -968,9 +972,9 @@
 	if((player_count == 1 && lms_dead_count == 1))
 	  	return WINNING_YES; // All dead... (n:n is handled by the test above)
 
-	dprint("player count = "); dprint(ftos(player_count));
-	dprint(", dead count = "); dprint(ftos(lms_dead_count));
-	dprint("\n");
+	// dprint("player count = "); dprint(ftos(player_count));
+	// dprint(", dead count = "); dprint(ftos(lms_dead_count));
+	// dprint("\n");
 
 	// When we get here, we have at least two players who are actually LIVING,
 	// or one player who is still waiting for a victim to join the server. Now




More information about the nexuiz-commits mailing list