diff -u xmms-cvs/xmms/main.c xmms/xmms/main.c
--- xmms-cvs/xmms/main.c	Fri Apr 26 11:41:18 2002
+++ xmms/xmms/main.c	Fri Apr 26 12:14:40 2002
@@ -346,7 +346,7 @@
 	cfg.random_skin_on_play = FALSE;
 	cfg.mainwin_use_xfont = FALSE;
 	cfg.read_pl_metadata = TRUE;
-
+	cfg.use_scoring = FALSE;
 	cfg.playlist_x = 295;
 	cfg.playlist_y = 20;
 	cfg.playlist_width = 300;
@@ -397,6 +397,7 @@
 		xmms_cfg_read_boolean(cfgfile, "xmms", "no_playlist_advance", &cfg.no_playlist_advance);
 		xmms_cfg_read_boolean(cfgfile, "xmms", "sort_jump_to_file", &cfg.sort_jump_to_file);
 		xmms_cfg_read_boolean(cfgfile, "xmms", "read_pl_metadata", &cfg.read_pl_metadata);
+		xmms_cfg_read_boolean(cfgfile, "xmms", "use_scoring", &cfg.use_scoring);
 		xmms_cfg_read_boolean(cfgfile, "xmms", "smooth_title_scroll", &cfg.smooth_title_scroll);
 		xmms_cfg_read_boolean(cfgfile, "xmms", "use_backslash_as_dir_delimiter", &cfg.use_backslash_as_dir_delimiter);
 		xmms_cfg_read_int(cfgfile, "xmms", "player_x", &cfg.player_x);
@@ -556,6 +557,7 @@
 	xmms_cfg_write_boolean(cfgfile, "xmms", "save_window_positions", cfg.save_window_position);
 	xmms_cfg_write_boolean(cfgfile, "xmms", "dim_titlebar", cfg.dim_titlebar);
 	xmms_cfg_write_boolean(cfgfile, "xmms", "read_pl_metadata", cfg.read_pl_metadata);
+	xmms_cfg_write_boolean(cfgfile, "xmms", "use_scoring", cfg.use_scoring);
 	xmms_cfg_write_boolean(cfgfile, "xmms", "get_info_on_load", cfg.get_info_on_load);
 	xmms_cfg_write_boolean(cfgfile, "xmms", "get_info_on_demand", cfg.get_info_on_demand);
 	xmms_cfg_write_boolean(cfgfile, "xmms", "eq_doublesize_linked", cfg.eq_doublesize_linked);
@@ -677,6 +679,11 @@
 	g_free(filename);
 	filename = g_strconcat(g_get_home_dir(), "/.xmms/xmms.m3u", NULL);
 	playlist_save(filename);
+	
+	/* re-random playlist in case use_scoring has changed */
+	if (mainwin_shuffle->tb_selected) 
+		playlist_generate_shuffle_list();
+		
 	g_free(filename);
 }
 
diff -u xmms-cvs/xmms/main.h xmms/xmms/main.h
--- xmms-cvs/xmms/main.h	Fri Apr 26 11:41:18 2002
+++ xmms/xmms/main.h	Fri Apr 26 11:52:40 2002
@@ -60,6 +60,7 @@
 	gint mouse_change;
 	gboolean playlist_transparent;
 	gchar *gentitle_format;
+	gboolean use_scoring;
 }
 Config;
 
diff -u xmms-cvs/xmms/playlist.c xmms/xmms/playlist.c
--- xmms-cvs/xmms/playlist.c	Fri Apr 26 11:41:18 2002
+++ xmms/xmms/playlist.c	Fri Apr 26 12:17:56 2002
@@ -22,7 +22,7 @@
 #include "libxmms/util.h"
 #include <sys/stat.h>
 #include <unistd.h>
-
+#include <assert.h>
 GList *playlist = NULL;
 GList *shuffle_list = NULL;
 static gboolean playlist_get_info_scan_active = FALSE;
@@ -219,7 +219,7 @@
 	}
 }
 
-static void __playlist_ins_with_info(char *filename, long pos, char* title, int len)
+static void __playlist_ins_with_info(char *filename, long pos, char* title, int len, int score)
 {
 	PlaylistEntry *entry;
 
@@ -228,7 +228,7 @@
 	if (title)
 		entry->title = g_strdup(title);
 	entry->length = len;
-
+	entry->score  = score;
 	pthread_mutex_lock(&playlist_mutex);
 	playlist = g_list_insert(playlist, entry, pos);
 	pthread_mutex_unlock(&playlist_mutex);		
@@ -238,7 +238,7 @@
 
 static void __playlist_ins(char * filename, long pos)
 {
-	__playlist_ins_with_info(filename, pos, NULL, -1);
+	__playlist_ins_with_info(filename, pos, NULL, -1, 0);
 }
 
 static gboolean is_playlist_name(char *pathname)
@@ -534,7 +534,6 @@
 {
 	GList *plist_pos_list;
 	gboolean restart_playing = FALSE;
-
 	PL_LOCK();
 	if (!playlist)
 	{
@@ -543,7 +542,9 @@
 	}
 
 	plist_pos_list = find_playlist_position_list();
-
+	if (cfg.shuffle) {
+		playlist_score_file(-1);
+	}
 	if (!cfg.repeat && !g_list_next(plist_pos_list))
 	{
 		PL_UNLOCK();
@@ -598,7 +599,9 @@
 	}
 
 	plist_pos_list = find_playlist_position_list();
-
+	if (cfg.shuffle) {
+		playlist_score_file(-1);
+	}
 	if (!cfg.repeat && !g_list_previous(plist_pos_list))
 	{
 		PL_UNLOCK();
@@ -648,6 +651,7 @@
 	GList *node;
 	gboolean restart_playing = FALSE;
 	
+	playlist_score_file(-1);
 	PL_LOCK();
 	if (!playlist)
 	{
@@ -682,6 +686,18 @@
 		mainwin_set_info_text();
 		playlistwin_update_list();
 	}
+	playlist_score_file(+1);
+}
+
+void playlist_score_file(gint factor) 
+{
+	if(!get_input_playing() && factor==-1) {
+		return;
+	}
+	if(playlist_position->score < -19 || playlist_position->score > 19) {
+		return;
+	}
+	playlist_position->score += factor;
 }
 
 void playlist_eof_reached(void)
@@ -857,8 +873,8 @@
 				else
 					seconds = -1;
 
-				fprintf(file, "#EXTINF:%d,%s\n",
-					seconds, entry->title);
+				fprintf(file, "#EXTINF:%d,%s,%d\n",
+					seconds, entry->title,entry->score);
 			}
 			fprintf(file, "%s\n", entry->filename);
 		}
@@ -874,7 +890,7 @@
 	return playlist_load_ins(filename, -1);
 }
 
-static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len)
+static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len, int score)
 {
 	gchar *temp, *path;
 
@@ -894,25 +910,25 @@
 			*temp = '\0';
 		else
 		{
-			__playlist_ins_with_info(filename, pos, title, len);
+			__playlist_ins_with_info(filename, pos, title, len, score);
 			return;
 		}
 		temp = g_strdup_printf("%s/%s", path, filename);
-		__playlist_ins_with_info(temp, pos, title, len);
+		__playlist_ins_with_info(temp, pos, title, len, score);
 		g_free(temp);
 		g_free(path);
 	}
 	else
-		__playlist_ins_with_info(filename, pos, title, len);
+		__playlist_ins_with_info(filename, pos, title, len, score);
 }
 
-static void parse_ext3u_info(char *info, char **title, int *length)
+static void parse_ext3u_info(char *info, char **title, int *length, int *score)
 {
 	char *str;
-	
+	char *str_score;
 	*title = NULL;
 	*length = -1;
-
+	*score = 0;
 	if (!info)
 		return;
 
@@ -926,6 +942,12 @@
 	if ((str = strchr(info, ',')) != NULL)
 	{
 		*title = g_strdup(str + 1);
+		if(str!= (str_score = strrchr(info, ','))){
+			if(str_score != NULL) {
+				*title = g_strndup(*title, strlen(*title)-strlen(str_score));
+			}
+		}
+		
 		g_strstrip(*title);
 		if (strlen(*title) < 1)
 		{
@@ -933,6 +955,11 @@
 			*title = NULL;
 		}
 	}
+	if(str != NULL && str!= (str_score = strrchr(info, ','))) {
+		if(str_score != NULL) {
+			*score = atoi(str_score+1);
+		}
+	}
 }
 
 guint playlist_load_ins(gchar * filename, glong pos)
@@ -943,7 +970,7 @@
 	int linelen = 1024;
 	gboolean extm3u = FALSE;
 	char *ext_info = NULL, *ext_title = NULL;
-	int ext_len = -1;
+	int ext_len = -1, ext_score = 0;
 
 	ext = strrchr(filename, '.');
 	if (ext && !strcasecmp(ext, ".pls"))
@@ -965,7 +992,7 @@
 			if (line != NULL)
 			{
 				playlist_load_ins_file(line, filename, pos,
-						       NULL, -1);
+						       NULL, -1, 0);
 				entries++;
 				if (pos >= 0)
 					pos++;
@@ -1027,16 +1054,17 @@
 		if (extm3u)
 		{
 			if (cfg.read_pl_metadata)
-				parse_ext3u_info(ext_info, &ext_title, &ext_len);
+				parse_ext3u_info(ext_info, &ext_title, &ext_len, &ext_score);
 			g_free(ext_info);
 			ext_info = NULL;
 		}
 		
-		playlist_load_ins_file(line, filename, pos, ext_title, ext_len);
+		playlist_load_ins_file(line, filename, pos, ext_title, ext_len, ext_score);
 		
 		g_free(ext_title);
 		ext_title = NULL;
 		ext_len = -1;
+		ext_score = 0;
 		
 		entries++;
 		if (pos >= 0)
@@ -1363,6 +1391,18 @@
 	PL_UNLOCK();
 }
 
+static int sort_score(const void *a, const void *b)
+{
+        
+        int score_a = (*((PlaylistEntry **)a))->score;
+        int score_b = (*((PlaylistEntry **)b))->score;
+
+        /* We want high scores before low, so if score_a > score_b we
+           want to return something negative. */
+        
+        return score_b - score_a;
+} 	
+
 static GList *playlist_shuffle_list(GList *list)
 {
 	/* Caller should holde playlist mutex */
@@ -1403,11 +1443,104 @@
 	return list;
 }
 
+static GList *playlist_shuffle_list_with_score(GList *list)
+{
+	/* Caller should holde playlist mutex */
+	/*
+	 * Note that this doesn't make a copy of the original list.
+	 * The pointer to the original list is not valid after this
+	 * fuction is run.
+	 */
+	gint len = g_list_length(list);
+	gint i, next_score_section=-1;
+	GList *current_node;
+	PlaylistEntry **entries;
+	
+	if (len==0)
+		return NULL;
+
+	entries = g_new(PlaylistEntry *, len);
+	for (current_node = list, i = 0; i < len; current_node = g_list_next(current_node), i++)
+	{
+		entries[i] = (PlaylistEntry *)(current_node->data);
+	}
+        g_list_free(list);
+        list = NULL;
+
+        /* Sort by score */
+        qsort(entries, len, sizeof(PlaylistEntry *), sort_score);
+
+        /* Shuffle */
+        for (i = 0; i < len; i++)
+        {
+                PlaylistEntry *temp_entry;
+                gint j;
+                
+                if (i >= next_score_section)
+                {
+                        gint current_score = entries[i]->score;
+                        
+                        for (next_score_section = i; next_score_section < len; next_score_section++)
+                        {
+                                if (entries[next_score_section]->score != current_score)
+                                {
+                                        break;
+                                }
+                        }
+                }
+
+                /* Find out from which index we should get the next song */
+                do {
+                                j = (rand() % (next_score_section - i)) + i;
+
+                                assert(j < next_score_section);
+                } while (j == -1);
+
+                assert(j < len);
+                assert(j >= i);
+                
+                if (j < next_score_section)
+                {
+                        /* Swap pointer #i and pointer #j */
+                        temp_entry = entries[i];
+                        entries[i] = entries[j];
+                        entries[j] = temp_entry;
+			temp_entry = NULL;
+                }
+                else
+                {
+                        gint k;
+                        
+                        temp_entry = entries[i];
+                        entries[i] = entries[j];
+
+                        for (k = j; k >= (i + 2); k--)
+                        {
+                                entries[k] = entries[k - 1];
+                        }
+
+                        entries[i + 1] = temp_entry;
+                }
+        }
+
+        /* Create new list */
+        for (i = 0; i < len; i++)
+        {
+                list = g_list_append(list, entries[i]);
+        }
+ 
+ 	g_free(entries);
+	
+	return list;
+}
+
 void playlist_random(void)
 {
 	PL_LOCK();
-
-	playlist = playlist_shuffle_list(playlist);
+	if (cfg.use_scoring)
+		playlist = playlist_shuffle_list_with_score(playlist);
+	else
+		playlist = playlist_shuffle_list(playlist);
 
 	PL_UNLOCK();
 }
@@ -1445,7 +1578,10 @@
 	}
 	if (playlist)
 	{
-		shuffle_list = playlist_shuffle_list(g_list_copy(playlist));
+		if (cfg.use_scoring)
+			shuffle_list = playlist_shuffle_list_with_score(g_list_copy(playlist));
+		else
+			shuffle_list = playlist_shuffle_list(g_list_copy(playlist));
 		numsongs = g_list_length(shuffle_list);
 
 		if (!numsongs)
diff -u xmms-cvs/xmms/playlist.h xmms/xmms/playlist.h
--- xmms-cvs/xmms/playlist.h	Fri Apr 26 11:41:18 2002
+++ xmms/xmms/playlist.h	Fri Apr 26 11:42:14 2002
@@ -26,6 +26,7 @@
 	gchar *title;
 	gint length;
 	gboolean selected;
+	gint score;
 }
 PlaylistEntry;
 
@@ -47,6 +48,7 @@
 void playlist_prev(void);
 void playlist_eof_reached(void);
 void playlist_set_position(gint pos);
+void playlist_score_file(gint factor);
 gint get_playlist_length(void);
 gint __get_playlist_length(void);
 gint get_playlist_position(void);
diff -u xmms-cvs/xmms/prefswin.c xmms/xmms/prefswin.c
--- xmms-cvs/xmms/prefswin.c	Fri Apr 26 11:41:18 2002
+++ xmms/xmms/prefswin.c	Fri Apr 26 11:51:22 2002
@@ -996,6 +996,7 @@
 	gtk_table_attach_defaults(GTK_TABLE(options_table), options_mouse_box, 0, 1, 8, 9);
 	
 	prefswin_option_new_with_label_to_table(&cfg.read_pl_metadata, _("Read meta data from playlists"), GTK_TABLE(options_table), 1, 8);
+	prefswin_option_new_with_label_to_table(&cfg.use_scoring, _("Score random playing"), GTK_TABLE(options_table), 0, 10);
 
 	gtk_notebook_append_page(GTK_NOTEBOOK(prefswin_notebook), prefswin_options_vbox, gtk_label_new(_("Options")));
 
