diff --git a/src/command.c b/src/command.c
index d39730f98..0a0b62956 100644
--- a/src/command.c
+++ b/src/command.c
@@ -345,6 +345,40 @@ size_t COM_CheckParm(const char *check)
 	return 0;
 }
 
+/** \brief COM_CheckParm, but checks only the start of each argument.
+  *        E.g. checking for "-no" would match "-noerror" too.
+  */
+size_t COM_CheckPartialParm(const char *check)
+{
+	int  len;
+	size_t i;
+
+	len = strlen(check);
+
+	for (i = 1; i < com_argc; i++)
+	{
+		if (strncasecmp(check, com_argv[i], len) == 0)
+			return i;
+	}
+	return 0;
+}
+
+/** Find the first argument that starts with a hyphen (-).
+  * \return The index of the argument, or 0
+  *         if there are no such arguments.
+  */
+size_t COM_FirstOption(void)
+{
+	size_t i;
+
+	for (i = 1; i < com_argc; i++)
+	{
+		if (com_argv[i][0] == '-')/* options start with a hyphen */
+			return i;
+	}
+	return 0;
+}
+
 /** Parses a string into command-line tokens.
   *
   * \param ptext A null-terminated string. Does not need to be
diff --git a/src/command.h b/src/command.h
index 4682ba4a4..d324481f7 100644
--- a/src/command.h
+++ b/src/command.h
@@ -29,6 +29,8 @@ size_t COM_Argc(void);
 const char *COM_Argv(size_t arg); // if argv > argc, returns empty string
 char *COM_Args(void);
 size_t COM_CheckParm(const char *check); // like M_CheckParm :)
+size_t COM_CheckPartialParm(const char *check);
+size_t COM_FirstOption(void);
 
 // match existing command or NULL
 const char *COM_CompleteCommand(const char *partial, INT32 skips);
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 485b53719..3ccab0a8e 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1719,56 +1719,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
 	}
 }
 
-enum
-{
-	MAP_COMMAND_FORCE_OPTION,
-	MAP_COMMAND_GAMETYPE_OPTION,
-	MAP_COMMAND_NORESETPLAYERS_OPTION,
-
-	NUM_MAP_COMMAND_OPTIONS
-};
-
-static size_t CheckOptions(
-		int            num_options,
-		size_t       *first_argumentp,
-		size_t       *user_options,
-		const char ***option_names,
-		int          *option_num_arguments
-)
-{
-	int    arguments_used;
-	size_t first_argument;
-
-	int i;
-	const char **pp;
-	const char  *name;
-	size_t n;
-
-	arguments_used = 0;
-	first_argument = COM_Argc();
-
-	for (i = 0; i < num_options; ++i)
-	{
-		pp = option_names[i];
-		name = *pp;
-		do
-		{
-			if (( n = COM_CheckParm(name) ))
-			{
-				user_options[i] = n;
-				arguments_used += 1 + option_num_arguments[i];
-				if (n < first_argument)
-					first_argument = n;
-			}
-		}
-		while (( name = *++pp )) ;
-	}
-
-	(*first_argumentp) = first_argument;
-
-	return arguments_used;
-}
-
 static char *
 ConcatCommandArgv (int start, int end)
 {
@@ -1812,43 +1762,10 @@ ConcatCommandArgv (int start, int end)
 //
 static void Command_Map_f(void)
 {
-	const char  *force_option_names[] =
-	{
-		"-force",
-		"-f",
-		NULL
-	};
-	const char  *gametype_option_names[] =
-	{
-		"-gametype",
-		"-g",
-		"-gt",
-		NULL
-	};
-	const char  *noresetplayers_option_names[] =
-	{
-		"-noresetplayers",
-		NULL
-	};
-	const char **option_names[] =
-	{
-		force_option_names,
-		gametype_option_names,
-		noresetplayers_option_names,
-	};
-	int         option_num_arguments[] =
-	{
-		0,/* -force */
-		1,/* -gametype */
-		0,/* -noresetplayers */
-	};
-
-	size_t acceptableargc;/* (this includes the command name itself!) */
-	size_t first_argument;
-
-	size_t      user_options         [NUM_MAP_COMMAND_OPTIONS] = {0};
-
-	const char *arg_gametype;
+	size_t first_option;
+	size_t option_force;
+	size_t option_gametype;
+	const char *gametypename;
 	boolean newresetplayers;
 
 	boolean mustmodifygame;
@@ -1871,18 +1788,15 @@ static void Command_Map_f(void)
 		return;
 	}
 
-	/* map name + options */
-	acceptableargc = 2 + CheckOptions(NUM_MAP_COMMAND_OPTIONS,
-			&first_argument,
-			user_options, option_names, option_num_arguments);
-
-	newresetplayers = !user_options[MAP_COMMAND_NORESETPLAYERS_OPTION];
+	option_force    =   COM_CheckPartialParm("-f");
+	option_gametype =   COM_CheckPartialParm("-g");
+	newresetplayers = ! COM_CheckParm("-noresetplayers");
 
 	mustmodifygame =
 		!( netgame     || multiplayer ) &&
 		(!modifiedgame || savemoddata );
 
-	if (mustmodifygame && !user_options[MAP_COMMAND_FORCE_OPTION])
+	if (mustmodifygame && !option_force)
 	{
 		/* May want to be more descriptive? */
 		CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
@@ -1895,26 +1809,37 @@ static void Command_Map_f(void)
 		return;
 	}
 
-	if (user_options[MAP_COMMAND_GAMETYPE_OPTION] && !multiplayer)
+	if (option_gametype)
 	{
-		CONS_Printf(M_GetText("You can't switch gametypes in single player!\n"));
-		return;
+		if (!multiplayer)
+		{
+			CONS_Printf(M_GetText(
+						"You can't switch gametypes in single player!\n"));
+			return;
+		}
+		else if (COM_Argc() < option_gametype + 2)/* no argument after? */
+		{
+			CONS_Alert(CONS_ERROR,
+					"No gametype name follows parameter '%s'.\n",
+					COM_Argv(option_gametype));
+			return;
+		}
 	}
 
-	/* If the first argument is an option, you fucked up. */
-	if (COM_Argc() < acceptableargc || first_argument == 1)
+	if (!( first_option = COM_FirstOption() ))
+		first_option = COM_Argc();
+
+	if (first_option < 2)
 	{
 		/* I'm going over the fucking lines and I DON'T CAREEEEE */
 		CONS_Printf("map <name / [MAP]code / number> [-gametype <type>] [-force]:\n");
 		CONS_Printf(M_GetText(
 					"Warp to a map, by its name, two character code, with optional \"MAP\" prefix, or by its number (though why would you).\n"
-					"All parameters are case-insensitive.\n"
-					"* \"-force\" may be shortened to \"-f\".\n"
-					"* \"-gametype\" may be shortened to \"-g\" or \"-gt\".\n"));
+					"All parameters are case-insensitive and may be abbreviated.\n"));
 		return;
 	}
 
-	mapname = ConcatCommandArgv(1, first_argument);
+	mapname = ConcatCommandArgv(1, first_option);
 	mapnamelen = strlen(mapname);
 
 	if (mapnamelen == 2)/* maybe two digit code */
@@ -1965,22 +1890,22 @@ static void Command_Map_f(void)
 		realmapname = G_BuildMapTitle(newmapnum);
 	}
 
-	if (mustmodifygame && user_options[MAP_COMMAND_FORCE_OPTION])
+	if (mustmodifygame && option_force)
 	{
 		G_SetGameModified(false);
 	}
 
 	// new gametype value
 	// use current one by default
-	if (user_options[MAP_COMMAND_GAMETYPE_OPTION])
+	if (option_gametype)
 	{
-		arg_gametype = COM_Argv(user_options[MAP_COMMAND_GAMETYPE_OPTION] + 1);
+		gametypename = COM_Argv(option_gametype + 1);
 
-		newgametype = G_GetGametypeByName(arg_gametype);
+		newgametype = G_GetGametypeByName(gametypename);
 
 		if (newgametype == -1) // reached end of the list with no match
 		{
-			d = atoi(arg_gametype);
+			d = atoi(gametypename);
 			// assume they gave us a gametype number, which is okay too
 			if (d >= 0 && d < NUMGAMETYPES)
 				newgametype = d;
@@ -1988,7 +1913,7 @@ static void Command_Map_f(void)
 	}
 
 	// don't use a gametype the map doesn't support
-	if (cv_debug || user_options[MAP_COMMAND_FORCE_OPTION] || cv_skipmapcheck.value)
+	if (cv_debug || option_force || cv_skipmapcheck.value)
 		fromlevelselect = false; // The player wants us to trek on anyway.  Do so.
 	// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
 	else
@@ -2043,7 +1968,6 @@ static void Command_Map_f(void)
 
 	Z_Free(realmapname);
 }
-#undef CHECKPARM
 
 /** Receives a map command and changes the map.
   *