ID:938839
 
Ok, so yeah, if you can't tell from the included snippet, I don't know what I'm doing, just want you to have no illusions about that. IMO not only bad programming, but bad use of byond coding, and most likely a terrifying use of a proc, and a terrible comprehension of OOP.

All of that aside, this proc does work(ish), albeit with a few minor glitches (see below code). That isn't really the main point of this post, rather I would like to know how to make this code more elegant, proper, and even more generalized, I know I must have some really bad habits (as I have really only ever programmed in applesofts basic way back in the early 80's, spaghetti programming is what I was best at, goto and gosub were my bestest friends) I would like help identifying these problems and perhaps start to correct them. The code is included so you can get a glimpse into how my mind works, and some things I might like to accomplish with this part of the code.

This part of the Code: is called with spawn(metab) rattai()
And it pertains to a game of survival, albeit for the ratt and its ai (such as it is).

Things the ratt needs to survive:
1) make a nest (find water first and build near it, but not too near)
2) find food, kill it, eat it if hungry, if not, drop it IN the nest
3) drink water when thirsty
4) avoid dangerous mobs (unless too near nest or when very hungry.)
5) get slight bonuses when close to nest, faster speed, quicker to react in combat, better th (aka THAC0) and more damage.

I think that covers the basics for the ratt and its ai.

  proc/rattai()
if (get_dist(src,nestloc)<=5)
metab=9
init=7
th=20
mindam=2
maxdam=3
else
metab=12
init=8
th=22
mindam=1
maxdam=2
if (hp>0&&incombat==0)
for (var/mob/M as mob in oview(6))
if (!action&&get_dist(M,src)<5&&!istype(M,/mob/frogg)&&get_dist(M,src)>1)
if (get_dist(src,nestloc)<=5&&get_dist(M,nestloc)<=5)
step_to(src,M)
world<<"[src]: SQUEAK! Get away from my nest!"
action=1
else
if(food<=2)
step_to(src,M)
if(get_dist(src,M)<=1)
attack(M)
action=1
else
step_away(src,M)
world<<"[src]: Squeak! Run away!"
action=1
if (!action&&get_dist(src,nestloc)<=5&&get_dist(M,nestloc)<=5&&get_dist(M,src)<=1)
attack(M)
action=1
if (!action&&get_dist(M,src)>1&&istype(M,/mob/frogg)&&(food<=7||mouth==0))
step_to(src,M)
world<<"[src]: Yum! Get me some! [get_dist(M,src)]"
action=1
if (!action&&get_dist(M,src)<=1&&istype(M,/mob/frogg))
world<<"[src]: Gimme those legs!"
M.drop()
froggs.len-=1
chkfrg()
del(M)
action=1
for (var/obj/O as obj in oview(5))
if (!action&&mouth==0||food<=7)
if (!action&&get_dist(O,src)>1&&istype(O,/obj/frogglegs))
step_to(src,O)
action=1
world<<"[src]: Those look yummy!"
if (!action&&get_dist(O,src)<=1&&istype(O,/obj/frogglegs)&&food<=7)
food+=3
action=1
world<<"[src]: Munch munch.."
del(O)
if (!action&&get_dist(O,src)<=1&&istype(O,/obj/frogglegs)&&food>7&&(get_dist(O,nestloc)>0 || !(O in nestloc)))
O.loc=src
mouth=1
action=1
world<<"[src]: mMrmph [O]"
if (!action&&!nest&&!waterfound)
for (var/turf/T as turf in oview(5))
if (istype(T,/turf/water))
waterfound=1
step_away(src,T)
world<<"[src]: I see water"
waterloc+=T
action=1
break
if(!action&&!nest&&waterfound)
if(get_dist(src,waterloc)>=6)
var/obj/o=new /obj/rattsnest
o.loc=loc
o.owner=src
nestloc=o
nest=1
action=1
else
spawn(1)
while(get_dist(src,waterloc)<6)
step_rand(src)
sleep(metab)
var/obj/o=new /obj/rattsnest
o.loc=loc
o.owner=src
nestloc=o
nest=1
action=1
if (!action)
step_rand(src)
action=1
if (!action&&nest&&mouth==1)
if (!get_dist(src,nestloc))
for (var/obj/o in contents)
o.loc=nestloc
action=1
mouth=0
world<<"[src]: patooey"
else
step_to(src,nestloc)
action=1
if(!action&&food<=7&&mouth==1)
mouth=0
food+=3
for (var/obj/o in contents)
del(o)
action=1
if(!action&&food<=7)
for(var/obj/o in nestloc)
if(o)
if(get_dist(src,nestloc)>0)
step_to(src,nestloc)
action=1
break
else
food+=3
del(o)
action=1
break
if (!action&&water<=1)
step_to(src,waterloc)
if(get_dist(src,waterloc)<=1)
water=watermax
action=1
if (!action)
step_rand(src)
action=1
action=0
spawn(metab) rattai()


Problem description: as I stated above, this code does work(ish) there are a few glitches, like the ratt can't change its mind, once its on a path it has no choice but to complete that path and if something disturbs completion errors can occur. (mostly just stuck looping, for example hungry (but not very hungry) and a dangerous mob is in the way of its nest (where it knows it has stored food) can cause a run away and move back towards nest kind of loop, and others along those same lines.

Sorry for such a long post, but I wasn't sure I could get my points across without including as much as I did.

Instead of calling the proc inside itself( using spawn() proc() ) is bad, you should replace it with a while() loop.

Other than that, the code is really clunky and most of it is un-needed. I'll continue to read through it and let you know of every correction I can offer, and probably find your issue aswell.
You seem to include a bunch of if(!action&&...) calls in your for() loops, this is un-needed. You could simply include one if(!action) and break the loop.

Also, you don't seem to tell the 'rat' that it's found something; I recomend making a variable to resinate who/what to goto. I'll give you examples below.

mob/rat/proc/search()
while(src)
if(action){ sleep(time); continue; }//if creature is busy, do nothing
if(movingto)//if creature is currently looking for something, only go for that.
if(movingto in view(5,src))
step_to(src,movingto)
else movingto=null
else
for(var/atom/movable/a in view(4,src))//check through objs and mobs
if(ismob(a))
view(src)<<"Back off!"
movingto=a
sleep(time)
break //breaks the for()
if(istype(a,/obj/food)||istype(a,/obj/water))
view(src)<<"Yum!"
movingto=a
sleep(time)
break

Honestly, you'd have to redo the entire proc.
In response to NNAAAAHH (#2)
Oh, thank you NNAAAAHH for the tips so far, me LIKEY! And I had no illusions about keeping this code, as I know its terrible.

I did consider the while() loop, but wasn't sure how to make it pause for metab amount of time, as I had thought that sleep waits to continue whereas spawn waits but lets other procs also continue, I guess I should go back and read these again.

So, what I'm sayin, is keep it comin! I'll take any criticism or any better ideas or better ways of doing things, as long as things can be kept as general as possible to re-use the code obviously for other mobs that may want to use the same sort of procs.

Even the little things, like making /obj(s) include a 'food' category and of course they would need a /var for food_value or something to determine how much food increase they get for eating said food (so far only frogglegs can be eaten so I just hard coded that as 3).

And if you think this code is bad, wait till I show ya the attack() proc I made, that was too laughable to even print!

Thanks again for taking the time to help, as I really just want to have a better understanding of what it is I'm supposed to be doing. (Byond>OOP>programming) Do I have that in the right order?

Since I don't actually del(src) when it dies can the while loop be while(!action) instead? Can that work? Yeah, I just typed it, and can already see that would be a problem... so perhaps while(hp>0) or something instead?
In response to Some Slacker (#3)
That while(src.hp<=0) could work, why don't you delete the NPC when it dies? But if anything, you can make a clause inside the while.

while(src)
if(hp<=0){ sleep(time); continue; }//this assumes you heal it at one point.

sleep() holds up the proc it's called in, it's prefectly fine to use.

mob/rat/New()
..()
spawn() search()

Using spawn() when you call the proc will allow it to continue the proc you called it in without haulting it.
There is no logical reason I didn't del(src) when it dies, other than eventually I wanted it to retain some of its knowledge reserving the del(src) until I was ready for it to forget what (if anything) it had 'learned' up to that point. Things like, where its water is, where its nest is, any experience it had gained or levels attained etc. without having to repop all the vars to do so.

And thanks for a better explanation of spawn/sleep

And yes hp's do eventually come back, he spends some time in 'dead' state then goes invisible and drops whatever it is he's made of, for a longer time (even longer if he doesn't have a nest) and will eventually re-spawn near where he died (without a nest) or somewhere near its nest (if it has one).

And keep in mind this isn't for some game I've imagined, its all just experimentation, basically to see if I could figure out how to do anything at all (there were moments when I was doubtful) and as you can see from my code, I have no 'knack' or innate abilities to program, and even though I did read (and re-read) the guide and ref along with some tuts, I had at least gotten past just assignations, getting to a point of wondering 'I wonder if I could...(whatever)' And in this case, its turning out to be, I wonder if I could make a survival game, where the NPC's try and survive as well, rather than just waiting for me to kill them.