ID:2259275
 
(See the best response by Nadrew.)
Descriptive Problem Summary:

I have a deathCheck proc that relocates the enemy mob at random coordinates from 1 to 15 for both x and y position. For some reason, when the deathCheck goes off, it tends to give the /exact/ same coordinates, twice, three times, even four times in a row. I don't see any issues with my code and I think this needs to be looked into. I am using BYOND version 511.1380

Code Snippet (if applicable) to Reproduce Problem:
mob
var/hp
var/maxhp
var/strength

proc
deathCheck(var/mob/M)
world << "Enemy HP: [M.hp]"
if(M.hp <= 0)
M.hp = M.maxhp
M.Move(locate(rand(1,15), rand(1,15), 1))
world << "Enemy respawned at: [M.x], [M.y], [M.z]"

Player
icon = 'Mob.dmi'
icon_state = "Player"
hp = 10
maxhp = 10
strength = 2

verb
Attack()
for(var/mob/Enemy/e in enemyList)

if(src.dir == NORTH)
if(e.loc == locate(src.x, src.y + 1, src.z))
e.hp -= src.strength
src.deathCheck(e)

else if(src.dir == SOUTH)
if(e.loc == locate(src.x, src.y - 1, src.z))
e.hp -= src.strength
src.deathCheck(e)

else if(src.dir == WEST)
if(e.loc == locate(src.x - 1,src.y, src.z))
e.hp -= src.strength
src.deathCheck(e)

else if(src.dir == EAST)
if(e.loc == locate(src.x + 1, src.y, src.z))
e.hp -= src.strength
src.deathCheck(e)


Expected Results:

Different x and y coordinates from M.Move()

Actual Results:

Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 10, 6, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 3, 9, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 3, 9, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 15, 3, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 15, 3, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 2, 9, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 5, 3, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 13, 1, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 15, 1, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 15, 1, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 7, 10, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 7, 10, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 7, 10, 1
Enemy HP: 3
Enemy HP: 1
Enemy HP: -1
Enemy respawned at: 7, 3, 1

Does the problem occur:
Occurs during any non-hosted game session.

Workarounds:
None so far
There's technically no such thing as a random number on computers, there's always a formula at play that gives you quasi-random results using a seed. On BYOND the seed is based on the system clock so calls to rand() that happen within a small timespan tend to overlap (rarely).

You can alter this behavior by using rand_seed() to initialize the generator with your own seed to add a bit more randomness (but you'll need to change the seed each time, or the results will always be the same)

Your issue is that you're not accounting for failures in Move(), which is going to result in you seeing inconsistancies when movement is unsuccessful. The only time rand() tends to fail this way is when it's being called within the span of a couple of seconds, which I doubt you're doing here.

[Edit]

It should also be noted that you should probably be using world.maxx and world.maxy in rand() and not a static number, or you're gonna have to adjust the code anytime you change the size of your map.
I'd like to also add change your if-else spaghetti to switch()
Best response
Better yet, remove it outright and do

var/mob/enemy/e = locate() in get_step(src,src.dir)
if(e)
e.hp -= src.strength
src.deathCheck(e)


If there's a possibility of multiple enemies on a single tile, you'd want to loop over the turf returned by get_step() for them instead, but allowing that isn't usually good design.
The problem was that the map was only 15x10, so moves to locations off the map (null) failed. Also, it was outputting the mob's coordinates (sometimes unchanged due to movement failure) instead of the destination coordinates (which were fine as far as randomness goes).

(solved in the discord)
Was actually just abut to post something like that after I realized the almost reoccurring locate().
In response to Nadrew
Bless you.
In response to Kaiochao
Kaiochao wrote:
The problem was that the map was only 15x10, so moves to locations off the map (null) failed. Also, it was outputting the mob's coordinates (sometimes unchanged due to movement failure) instead of the destination coordinates (which were fine as far as randomness goes).

(solved in the discord)



I actually commented on accounting for failures in Move() and edited in the map size thing when it clicked that he had "15" and not maxx/maxy -- glad you guys got it sorted :)