Просмотр исходного кода

Improved randomness (part 1) (#7882)

Faster and with no module bias

Removed rnd_init, rnd_uint32 and rnd_uniform
From now on we will only use rnd_value(min, max) for values in range [min, max] and rnd_chance(chance, base) for chances

Fixes #7881
Fixes #7883
Fixes #7884
Fixes #7885

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Lemon 1 год назад
Родитель
Сommit
7c153416bc

+ 1 - 35
src/common/random.cpp

@@ -3,43 +3,9 @@
 
 #include "random.hpp"
 
-#include <random>
-
-std::mt19937 generator;
-std::uniform_int_distribution<int32> int31_distribution;
-std::uniform_int_distribution<uint32> uint32_distribution;
-
-/// Initializes the random number generator
-void rnd_init( void ){
-	std::random_device device;
-	generator = std::mt19937( device() );
-	int31_distribution = std::uniform_int_distribution<int32>( 0, SINT32_MAX );
-	uint32_distribution = std::uniform_int_distribution<uint32>( 0, UINT32_MAX );
-}
+std::uniform_int_distribution<int32> int31_distribution = std::uniform_int_distribution<int32>(0, SINT32_MAX);
 
 /// Generates a random number in the interval [0, SINT32_MAX]
 int32 rnd( void ){
 	return int31_distribution( generator );
 }
-
-/// Generates a random number in the interval [0, UINT32_MAX]
-uint32 rnd_uint32( void ){
-	return uint32_distribution( generator );
-}
-
-/// Generates a random number in the interval [0.0, 1.0)
-/// NOTE: interval is open ended, so 1.0 is excluded
-double rnd_uniform( void ){
-	return rnd_uint32() * ( 1.0 / 4294967296.0 );// divided by 2^32
-}
-
-/// Generates a random number in the interval [min, max]
-/// Returns min if range is invalid.
-int32 rnd_value( int32 min, int32 max ){
-	if( min >= max ){
-		return min;
-	}
-
-	return min + (int32)( rnd_uniform() * ( max - min + 1 ) );
-}
-

+ 22 - 4
src/common/random.hpp

@@ -4,15 +4,33 @@
 #ifndef RANDOM_HPP
 #define RANDOM_HPP
 
+#include <type_traits>
+#include <random>
+
 #include "cbasetypes.hpp"
 
-void rnd_init(void);
+inline std::random_device device;
+inline std::mt19937 generator = std::mt19937(device());
 
 int32 rnd(void);// [0, SINT32_MAX]
-int32 rnd_value(int32 min, int32 max);// [min, max]
 
-template <typename T> bool rnd_chance( T chance, T base ){
-	return rnd_value( 0, base ) < chance;
+/*
+ * Generates a random number in the interval [min, max]
+ * @return random number
+ */
+template <typename T>
+typename std::enable_if<std::is_integral<T>::value, T>::type rnd_value(T min, T max) {
+	std::uniform_int_distribution<T> dist(min, max);
+	return dist(generator);
+}
+
+/*
+ * Simulates a chance based on a given probability
+ * @return true if succeeded / false if it didn't
+ */
+template <typename T>
+typename std::enable_if<std::is_integral<T>::value, bool>::type rnd_chance(T chance, T base) {
+	return rnd_value<T>(1, base) <= chance;
 }
 
 #endif /* RANDOM_HPP */

+ 2 - 2
src/common/utilities.hpp

@@ -159,7 +159,7 @@ namespace rathena {
 		template <typename K, typename V> V& umap_random( std::unordered_map<K, V>& map ){
 			auto it = map.begin();
 
-			std::advance( it, rnd_value( 0, map.size() - 1 ) );
+			std::advance( it, rnd_value<size_t>( 0, map.size() - 1 ) );
 
 			return it->second;
 		}
@@ -172,7 +172,7 @@ namespace rathena {
 		template <typename K> K &vector_random(std::vector<K> &vec) {
 			auto it = vec.begin();
 
-			std::advance(it, rnd_value(0, vec.size() - 1));
+			std::advance( it, rnd_value<size_t>( 0, vec.size() - 1 ) );
 
 			return *it;
 		}

+ 2 - 4
src/login/login.cpp

@@ -403,8 +403,8 @@ int login_mmo_auth(struct login_session_data* sd, bool isServer) {
 
 	// update session data
 	sd->account_id = acc.account_id;
-	sd->login_id1 = rnd() + 1;
-	sd->login_id2 = rnd() + 1;
+	sd->login_id1 = rnd_value(1u, UINT32_MAX);
+	sd->login_id2 = rnd_value(1u, UINT32_MAX);
 	safestrncpy(sd->lastlogin, acc.lastlogin, sizeof(sd->lastlogin));
 	sd->sex = acc.sex;
 	sd->group_id = acc.group_id;
@@ -846,8 +846,6 @@ bool LoginServer::initialize( int argc, char* argv[] ){
 	login_lan_config_read(login_config.lanconf_name);
 	//end config
 
-	rnd_init();
-
 	do_init_loginclif();
 	do_init_loginchrif();
 

+ 2 - 2
src/login/login.hpp

@@ -39,8 +39,8 @@ namespace rathena{
 ///Struct of 1 client connected to login-serv
 struct login_session_data {
 	uint32 account_id;			///also GID
-	long login_id1;
-	long login_id2;
+	uint32 login_id1;
+	uint32 login_id2;
 	char sex;			/// 'F','M','S'
 
 	char userid[NAME_LENGTH];	/// account name

+ 1 - 2
src/login/loginclif.cpp

@@ -377,8 +377,7 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 static int logclif_parse_reqkey(int fd, struct login_session_data *sd){
 	RFIFOSKIP(fd,2);
 	{
-		memset(sd->md5key, '\0', sizeof(sd->md5key));
-		sd->md5keylen = (uint16)(12 + rnd() % 4);
+		sd->md5keylen = sizeof( sd->md5key );
 		MD5_Salt(sd->md5keylen, sd->md5key);
 
 		WFIFOHEAD(fd,4 + sd->md5keylen);

+ 4 - 4
src/map/atcommand.cpp

@@ -7259,7 +7259,7 @@ ACMD_FUNC(pettalk)
 		};
 		int i;
 		ARR_FIND( 0, ARRAYLENGTH(emo), i, stricmp(message, emo[i]) == 0 );
-		if( i == ET_DICE1 ) i = rnd()%6 + ET_DICE1; // randomize /dice
+		if( i == ET_DICE1 ) i = rnd_value<int>(ET_DICE1, ET_DICE6); // randomize /dice
 		if( i < ARRAYLENGTH(emo) )
 		{
 			if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second
@@ -8017,7 +8017,7 @@ ACMD_FUNC(hommutate)
 	}
 
 	if (!message || !*message) {
-		homun_id = 6048 + (rnd() % 4);
+		homun_id = rnd_value<uint16>(MER_EIRA, MER_ELEANOR);
 	} else {
 		homun_id = atoi(message);
 	}
@@ -9133,8 +9133,8 @@ ACMD_FUNC(clone)
 	}
 
 	do {
-		x = sd->bl.x + (rnd() % 10 - 5);
-		y = sd->bl.y + (rnd() % 10 - 5);
+		x = sd->bl.x + rnd_value(-5, 5);
+		y = sd->bl.y + rnd_value(-5, 5);
 	} while (map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10);
 
 	if (i >= 10) {

+ 1 - 1
src/map/battleground.cpp

@@ -1172,7 +1172,7 @@ void bg_queue_join_multi(const char *name, map_session_data *sd, std::vector <ma
 			break;
 		}
 
-		bool r = rnd() % 2 != 0;
+		bool r = rnd_chance(50, 100);
 		std::vector<map_session_data *> *team = r ? &queue->teamb_members : &queue->teama_members;
 
 		if (queue->state == QUEUE_STATE_ACTIVE) {

+ 2 - 2
src/map/clif.cpp

@@ -23561,11 +23561,11 @@ void clif_parse_laphine_upgrade( int fd, map_session_data* sd ){
 			item->refine = rnd_value( upgrade->resultRefineMinimum, upgrade->resultRefineMaximum );
 		}else{
 			// Otherwise it can only be upgraded until the maximum, but not downgraded
-			item->refine = rnd_value( item->refine, upgrade->resultRefineMaximum );
+			item->refine = rnd_value<uint16>( item->refine, upgrade->resultRefineMaximum );
 		}
 	}else if( upgrade->resultRefineMinimum > 0 ){
 		// No maximum has been specified, so it can be anything between minimum and MAX_REFINE
-		item->refine = rnd_value( upgrade->resultRefineMinimum, MAX_REFINE );
+		item->refine = rnd_value<uint16>( upgrade->resultRefineMinimum, MAX_REFINE );
 	}
 
 	// Log retrieving the item again -> with the new options

+ 1 - 1
src/map/elemental.cpp

@@ -622,7 +622,7 @@ static int elemental_ai_sub_timer(s_elemental_data *ed, map_session_data *sd, t_
 			return 1;
 		}
 
-		if( battle_check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill.
+		if( battle_check_range(&ed->bl,target,view_range) && rnd_chance(2, 100) ) { // 2% chance to cast attack skill.
 			if(	elemental_action(ed,target,tick) )
 				return 1;
 		}

+ 5 - 5
src/map/itemdb.cpp

@@ -2872,7 +2872,7 @@ std::shared_ptr<s_item_group_entry> get_random_itemsubgroup(std::shared_ptr<s_it
 	for (size_t j = 0, max = random->data.size() * 3; j < max; j++) {
 		std::shared_ptr<s_item_group_entry> entry = util::umap_random(random->data);
 
-		if (entry->rate == 0 || rnd() % random->total_rate < entry->rate)	// always return entry for rate 0 ('must' item)
+		if (entry->rate == 0 || rnd_chance<uint32>(entry->rate, random->total_rate))	// always return entry for rate 0 ('must' item)
 			return entry;
 	}
 
@@ -2956,9 +2956,9 @@ static void itemdb_pc_get_itemgroup_sub(map_session_data *sd, bool identify, std
 			if( data->refineMinimum > 0 && data->refineMaximum > 0 ){
 				tmp.refine = rnd_value( data->refineMinimum, data->refineMaximum );
 			}else if( data->refineMinimum > 0 ){
-				tmp.refine = rnd_value( data->refineMinimum, MAX_REFINE );
+				tmp.refine = rnd_value<uint16>( data->refineMinimum, MAX_REFINE );
 			}else if( data->refineMaximum > 0 ){
-				tmp.refine = rnd_value( 1, data->refineMaximum );
+				tmp.refine = rnd_value<uint16>( 1, data->refineMaximum );
 			}else{
 				tmp.refine = 0;
 			}
@@ -4456,7 +4456,7 @@ void s_random_opt_group::apply( struct item& item ){
 		for( size_t j = 0, max = this->slots[static_cast<uint16>(i)].size() * 3; j < max; j++ ){
 			std::shared_ptr<s_random_opt_group_entry> option = util::vector_random( this->slots[static_cast<uint16>(i)] );
 
-			if( rnd() % 10000 < option->chance ){
+			if ( rnd_chance<uint16>(option->chance, 10000) ) {
 				apply_sub( item.option[i], option );
 				break;
 			}
@@ -4481,7 +4481,7 @@ void s_random_opt_group::apply( struct item& item ){
 
 			std::shared_ptr<s_random_opt_group_entry> option = util::vector_random( this->random_options );
 
-			if( rnd() % 10000 < option->chance ){
+			if ( rnd_chance<uint16>(option->chance, 10000) ){
 				apply_sub( item.option[i], option );
 			}
 		}

+ 8 - 13
src/map/map.cpp

@@ -1669,7 +1669,7 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
 	}
 	if(free_cell==0)
 		return 0;
-	free_cell = rnd()%free_cell;
+	free_cell = rnd_value(0, free_cell-1);
 	*x = free_cells[free_cell][0];
 	*y = free_cells[free_cell][1];
 	return 1;
@@ -1697,8 +1697,6 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 {
 	int tries, spawn=0;
 	int bx, by;
-	int rx2 = 2*rx+1;
-	int ry2 = 2*ry+1;
 
 	if( !src && (!(flag&1) || flag&2) )
 	{
@@ -1728,7 +1726,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 	}
 
 	if (rx >= 0 && ry >= 0) {
-		tries = rx2*ry2;
+		tries = (rx * 2 + 1) * (ry * 2 + 1);
 		if (tries > 100) tries = 100;
 	} else {
 		tries = mapdata->xs*mapdata->ys;
@@ -1736,8 +1734,8 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 	}
 
 	while(tries--) {
-		*x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(mapdata->xs-2)+1);
-		*y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(mapdata->ys-2)+1);
+		*x = (rx >= 0) ? rnd_value(bx - rx, bx + rx) : rnd_value<int16>(1, mapdata->xs - 1);
+		*y = (ry >= 0) ? rnd_value(by - ry, by + ry) : rnd_value<int16>(1, mapdata->ys - 1);
 
 		if (*x == bx && *y == by)
 			continue; //Avoid picking the same target tile.
@@ -1860,7 +1858,6 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag)
  *------------------------------------------*/
 int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags, unsigned short mob_id, bool canShowEffect)
 {
-	int r;
 	struct flooritem_data *fitem = NULL;
 
 	nullpo_ret(item);
@@ -1870,7 +1867,6 @@ int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, i
 
 	if (!map_searchrandfreecell(m,&x,&y,flags&2?1:0))
 		return 0;
-	r = rnd();
 
 	CREATE(fitem, struct flooritem_data, 1);
 	fitem->bl.type=BL_ITEM;
@@ -1894,8 +1890,8 @@ int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, i
 
 	memcpy(&fitem->item,item,sizeof(*item));
 	fitem->item.amount = amount;
-	fitem->subx = (r&3)*3+3;
-	fitem->suby = ((r>>2)&3)*3+3;
+	fitem->subx = rnd_value(1, 4) * 3;
+	fitem->suby = rnd_value(1, 4) * 3;
 	fitem->cleartimer = add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
 
 	map_addiddb(&fitem->bl);
@@ -3090,8 +3086,8 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
 	if (dist < 1) dist =1;
 
 	do {
-		short j = 1 + 2*(rnd()%4); //Pick a random diagonal direction
-		short segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction
+		directions j = static_cast<directions>(1 + 2 * rnd_value(0, 3)); //Pick a random diagonal direction
+		short segment = rnd_value((short)1, dist); //Pick a random interval from the whole vector in that direction
 		xi = bl->x + segment*dirx[j];
 		segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
 		yi = bl->y + segment*diry[j];
@@ -5181,7 +5177,6 @@ bool MapServer::initialize( int argc, char *argv[] ){
 #endif
 	cli_get_options(argc,argv);
 
-	rnd_init();
 	map_config_read(MAP_CONF_NAME);
 
 	if (save_settings == CHARSAVE_NONE)

+ 1 - 1
src/map/mercenary.cpp

@@ -421,7 +421,7 @@ bool mercenary_dead(s_mercenary_data *md) {
 void mercenary_killbonus(s_mercenary_data *md) {
 	std::vector<sc_type> scs = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP };
 
-	sc_start(&md->bl,&md->bl, util::vector_random(scs), 100, rnd() % 5, 600000);
+	sc_start(&md->bl,&md->bl, util::vector_random(scs), 100, rnd_value(1, 5), 600000);
 }
 
 /**

+ 1 - 1
src/map/party.cpp

@@ -1278,7 +1278,7 @@ int party_share_loot(struct party_data* p, map_session_data* sd, struct item* it
 			}
 
 			while (count > 0) { //Pick a random member.
-				i = rnd()%count;
+				i = rnd_value(0, count-1);
 
 				if (pc_additem(psd[i],item,item->amount,LOG_TYPE_PICKDROP_PLAYER)) { // Discard this receiver.
 					psd[i] = psd[count-1];

+ 1 - 1
src/map/path.cpp

@@ -106,7 +106,7 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
 				int fy = ( dy != 0 && map_getcellp(mapdata,x0,y0+dy,CELL_CHKPASS) );
 				if( fx && fy )
 				{
-					if(rnd()&1)
+					if(rnd_chance(50, 100))
 						dx=0;
 					else
 						dy=0;

+ 9 - 9
src/map/pet.cpp

@@ -710,7 +710,7 @@ int pet_attackskill(struct pet_data *pd, int target_id)
 	if (DIFF_TICK(pd->ud.canact_tick, gettick()) > 0)
 		return 0;
 
-	if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) { // Skotlex: Use pet's skill
+	if (rnd_chance((pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000), 100)) { // Skotlex: Use pet's skill
 		int inf;
 		struct block_list *bl;
 
@@ -782,8 +782,8 @@ int pet_target_check(struct pet_data *pd,struct block_list *bl,int type)
 			rate = 1;
 	}
 
-	if(rnd()%10000 < rate) {
-		if(pd->target_id == 0 || rnd()%10000 < pet_db_ptr->change_target_rate)
+	if(rnd_chance(rate, 10000)) {
+		if(pd->target_id == 0 || rnd_chance<uint16>(pet_db_ptr->change_target_rate, 10000))
 			pd->target_id = bl->id;
 	}
 
@@ -942,7 +942,7 @@ static int pet_performance(map_session_data *sd, struct pet_data *pd)
 		val = 1;
 
 	pet_stop_walking(pd,2000<<8);
-	clif_pet_performance(pd, rnd()%val + 1);
+	clif_pet_performance(pd, rnd_value(1, val));
 	pet_lootitem_drop(pd,NULL);
 
 	return 1;
@@ -1315,7 +1315,7 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 	if(battle_config.pet_catch_rate != 100)
 		pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100;
 
-	if(rnd()%10000 < pet_catch_rate) {
+	if(rnd_chance(pet_catch_rate, 10000)) {
 		achievement_update_objective(sd, AG_TAMING, 1, md->mob_id);
 		unit_remove_map(&md->bl,CLR_OUTSIGHT);
 		status_kill(&md->bl);
@@ -1672,10 +1672,10 @@ static int pet_randomwalk(struct pet_data *pd,t_tick tick)
 			d = 5;
 
 		for(i = 0; i < retrycount; i++) {
-			int r = rnd(), x, y;
+			int x, y;
 
-			x = pd->bl.x+r%(d*2+1)-d;
-			y = pd->bl.y+r/(d*2+1)%(d*2+1)-d;
+			x = pd->bl.x + rnd_value(-d, d);
+			y = pd->bl.y + rnd_value(-d, d);
 
 			if(map_getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit_walktoxy(&pd->bl,x,y,0)) {
 				pd->move_fail_count = 0;
@@ -1702,7 +1702,7 @@ static int pet_randomwalk(struct pet_data *pd,t_tick tick)
 				c += pd->status.speed;
 		}
 
-		pd->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME+c;
+		pd->next_walktime = tick + MIN_RANDOMWALKTIME + c + rnd_value(0, 999);
 
 		return 1;
 	}

+ 1 - 1
src/map/quest.cpp

@@ -775,7 +775,7 @@ void quest_update_objective(map_session_data *sd, struct mob_data* md)
 		for (const auto &it : qi->dropitem) {
 			if (it->mob_id != 0 && it->mob_id != md->mob_id)
 				continue;
-			if (it->rate < 10000 && rnd()%10000 >= it->rate)
+			if (it->rate < 10000 && !rnd_chance<uint16>(it->rate, 10000))
 				continue; // TODO: Should this be affected by server rates?
 			if (!item_db.exists(it->nameid))
 				continue;

+ 13 - 13
src/map/script.cpp

@@ -5582,17 +5582,17 @@ BUILDIN_FUNC(rand)
 		min = script_getnum(st,2);
 		if( max < min )
 			SWAP(min, max);
-		range = max - min + 1;
+		range = max;
 	}
 	else
 	{// range
 		min = 0;
-		range = script_getnum(st,2);
+		range = script_getnum( st, 2 ) - 1;
 	}
 	if( range <= 1 )
 		script_pushint(st, min);
 	else
-		script_pushint(st, rnd()%range + min);
+		script_pushint( st, rnd_value( min, range ) );
 
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -5656,8 +5656,8 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap)
 
 		// find a suitable map cell
 		do {
-			tx = rnd()%(x3-x2+1)+x2;
-			ty = rnd()%(y3-y2+1)+y2;
+			tx = rnd_value(x2, x3);
+			ty = rnd_value(y2, y3);
 			j++;
 		} while( map_getcell(m,tx,ty,CELL_CHKNOPASS) && j < max );
 
@@ -5815,8 +5815,8 @@ BUILDIN_FUNC(warpparty)
 
 			i = 0;
 			do {
-				x = rnd()%(mapdata->xs - 2) + 1;
-				y = rnd()%(mapdata->ys - 2) + 1;
+				x = rnd_value(1, mapdata->xs - 1);
+				y = rnd_value(1, mapdata->ys - 1);
 			} while ((map_getcell(m,x,y,CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1,m,x,y,1))) && (i++) < 1000);
 
 			if (i >= 1000) {
@@ -5881,8 +5881,8 @@ BUILDIN_FUNC(warpparty)
 					uint8 attempts = 10;
 
 					do {
-						nx = x0 + rnd()%(x1 - x0 + 1);
-						ny = y0 + rnd()%(y1 - y0 + 1);
+						nx = x0 + rnd_value(x0, x1);
+						ny = y0 + rnd_value(y0, y1);
 					} while ((--attempts) > 0 && !map_getcell(m, nx, ny, CELL_CHKPASS));
 
 					if (attempts != 0) { //Keep the original coordinates if fails to find a valid cell within the range
@@ -10693,8 +10693,8 @@ BUILDIN_FUNC(savepoint)
 			x0 = x - dx, y0 = y - dy;
 		uint8 n = 10;
 		do {
-			x = x0 + rnd()%(x1-x0+1);
-			y = y0 + rnd()%(y1-y0+1);
+			x = rnd_value(x0, x1);
+			y = rnd_value(y0, y1);
 		} while (m != -1 && (--n) > 0 && !map_getcell(m, x, y, CELL_CHKPASS));
 	}
 
@@ -12536,7 +12536,7 @@ BUILDIN_FUNC(homunculus_evolution)
  *------------------------------------------*/
 BUILDIN_FUNC(homunculus_mutate)
 {
-	int homun_id;
+	uint16 homun_id;
 	TBL_PC *sd;
 
 	if( !script_rid2sd(sd) || sd->hd == NULL )
@@ -12545,7 +12545,7 @@ BUILDIN_FUNC(homunculus_mutate)
 	if(script_hasdata(st,2))
 		homun_id = script_getnum(st,2);
 	else
-		homun_id = 6048 + (rnd() % 4);
+		homun_id = rnd_value<uint16>(MER_EIRA, MER_ELEANOR);
 
 	if( sd->hd->homunculus.vaporize == HOM_ST_MORPH ) {
 		int m_class = hom_class2mapid(sd->hd->homunculus.class_);

+ 4 - 4
src/map/skill.cpp

@@ -1927,7 +1927,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint
 		break;
 	case LG_HESPERUSLIT:
 		if( pc_checkskill(sd,LG_PINPOINTATTACK) > 0 && sc && sc->getSCE(SC_BANDING) && sc->getSCE(SC_BANDING)->val2 > 5 )
-			skill_castend_damage_id(src,bl,LG_PINPOINTATTACK,rnd_value(1, pc_checkskill(sd,LG_PINPOINTATTACK)),tick,0);
+			skill_castend_damage_id(src,bl,LG_PINPOINTATTACK, rnd_value<uint16>(1, pc_checkskill(sd,LG_PINPOINTATTACK)),tick,0);
 		break;
 	case SR_DRAGONCOMBO:
 		sc_start(src,bl, SC_STUN, 1 + skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
@@ -2332,7 +2332,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint
 			uint16 autospl_skill_lv = it.lv ? it.lv : 1;
 
 			if (it.flag & AUTOSPELL_FORCE_RANDOM_LEVEL)
-				autospl_skill_lv = rnd_value( 1, autospl_skill_lv );
+				autospl_skill_lv = rnd_value<uint16>( 1, autospl_skill_lv );
 
 			int rate = (!sd->state.arrow_atk) ? it.rate : it.rate / 2;
 
@@ -2479,7 +2479,7 @@ int skill_onskillusage(map_session_data *sd, struct block_list *bl, uint16 skill
 		uint16 skill_lv = it.lv ? it.lv : 1;
 
 		if (it.flag & AUTOSPELL_FORCE_RANDOM_LEVEL)
-			skill_lv = rnd_value( 1, skill_lv ); //random skill_lv
+			skill_lv = rnd_value<uint16>( 1, skill_lv ); //random skill_lv
 
 		e_cast_type type = skill_get_casttype(skill);
 
@@ -2699,7 +2699,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 			uint16 autospl_skill_id = it.id, autospl_skill_lv = it.lv ? it.lv : 1;
 
 			if (it.flag & AUTOSPELL_FORCE_RANDOM_LEVEL)
-				autospl_skill_lv = rnd_value( 1, autospl_skill_lv );
+				autospl_skill_lv = rnd_value<uint16>( 1, autospl_skill_lv );
 
 			int autospl_rate = it.rate;
 

+ 2 - 2
src/map/unit.cpp

@@ -2603,7 +2603,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
 
 	nullpo_ret(ud);
 
-	if(dir > 7)
+	if(dir >= DIR_MAX || dir <= DIR_CENTER)
 		return 1;
 
 	ud->to_x = tx;
@@ -2630,7 +2630,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
 			int i;
 
 			for( i = 0; i < 12; i++ ) {
-				int k = rnd()%8; // Pick a Random Dir
+				int k = rnd_value<int>(DIR_NORTH, DIR_NORTHEAST); // Pick a Random Dir
 
 				dx = -dirx[k] * 2;
 				dy = -diry[k] * 2;