PDA

View Full Version : [2.xx] Expanded void Remove()



ZoriaRPG
06-05-2015, 01:54 AM
Internalise void Remove() so that it entirely kills any pointer object.

SUCCESSOR
06-07-2015, 04:05 PM
Internalise void Remove() so that it entirely kills any pointer object.

What exactly are you having problems removing?

ZoriaRPG
06-08-2015, 12:39 AM
Remove() does not fully invalidate pointers for datatypes ffc, item, lweapon, eweapon, and uses a substandard way to remove npc pointers. Have a look at what void Remove() does, and you'll understand.

An internal Remove() would fully remove the pointer.

SUCCESSOR
06-08-2015, 01:13 AM
Remove() does not fully invalidate pointers for datatypes ffc, item, lweapon, eweapon, and uses a substandard way to remove npc pointers. Have a look at what void Remove() does, and you'll understand.

An internal Remove() would fully remove the pointer.

Why would you need to remove the pointer? I know what Remove() does. I just fail to see what problem you have. Remove() doesn't do anything with pointers it gets rid of what they point to.

ZoriaRPG
06-08-2015, 03:13 AM
Why would you need to remove the pointer? I know what Remove() does. I just fail to see what problem you have. Remove() doesn't do anything with pointers it gets rid of what they point to.

Because isValid() still returns that the pointer exists, even if you do Remove(), and for loops still scan it, which lengthens loop time.

I wrote other functions to cover this, but it's still optimal to actually remove the pointer when it's no longer needed.

Gleeok
06-08-2015, 03:43 AM
Why would you need to remove the pointer? I know what Remove() does. I just fail to see what problem you have. Remove() doesn't do anything with pointers it gets rid of what they point to.

Remove is actually a bit of a hack. It doesn't really remove the object, it just makes it so that the next frame ZC will see that it should be removed (deleted). Internalizing it is actually a good suggestion, though actually deleting it might be bad. (Like my pappy used to say: Don't change horses midstream.) :smoke:

SUCCESSOR
06-08-2015, 04:14 AM
Remove is actually a bit of a hack. It doesn't really remove the object, it just makes it so that the next frame ZC will see that it should be removed (deleted). Internalizing it is actually a good suggestion, though actually deleting it might be bad. (Like my pappy used to say: Don't change horses midstream.) :smoke:

I get that. I know its a hack. I just don't see the useful difference to ZoriaRPG if it is internalized or not.


Because isValid() still returns that the pointer exists, even if you do Remove(), and for loops still scan it, which lengthens loop time.

I wrote other functions to cover this, but it's still optimal to actually remove the pointer when it's no longer needed.

So you want it to remove objects faster? Or are you saying you want if(pointer) to evaluate to false if it is invalid?

ZoriaRPG
06-08-2015, 04:53 AM
Right, isValid() should evaluate false when a pointer is specifically removed.Iit would avoid the hack-ish methods that I'm using to determine if it should be skipped. Again, for loops (especially with a Waitframe(), as those can become cumulative) would be optimised if pointers are removed. It would allow the loop to advance in the same frame, and wouldn't require workarounds for multiple loops that run per frame.

If you're curious, here is a set of utility functions that I use with the present Remove() function:




///Used to check if any given pointer is on screen. Move pointers to X = 32768 to effectively kill them with void Remove().
bool isOnScreen(item i){
if( i->isValid() && i->X != 32768 ) {
return true;
}
return false;
}

bool isOnScreen(ffc f){
if( f->Data > 0 && f->X != 32768 ) {
return true;
}
return false;
}

bool isOnScreen(npc n){
if( n->isValid() && n->X != 32768 ) {
return true;
}
return false;
}

bool isOnScreen(eweapon e){
if( e->isValid() && e->X != 32768 ) {
return true;
}
return false;
}

bool isOnScreen(lweapon l){
if( l->isValid() && l->X != 32768 ) {
return true;
}
return false;
}


I use those, in place of isValid(), which works for the present, but it would still be better to remove the pointers. They otherwise just use stack/ heap space anyway.

Again, it's a request for the future. It would be cleaner to remove the pointers, rather than moving them off-screen.

I can see how deleting the ZScript void Remove might be bad, if anything depends on it.

You could do void Rem() for the internal side, to prevent compatibility conflicts.

SUCCESSOR
06-08-2015, 07:33 AM
So basically what you are saying is you want to remove objects without waiting a frame. You could have just said that.

ZoriaRPG
06-08-2015, 10:50 AM
So basically what you are saying is you want to remove objects without waiting a frame. You could have just said that.

I could have, and then answered other questions from someone else, about why I don't want to wait a frame...

It's low priority, and for the record, I'll make suggestions for improvements, even if they don't directly pertain to my own goals. In this case, I have utility functions that mimic the behaviour that I need, but I've run into instances in other projects where this became an issue. That notwithstanding, I would likely have made this suggestion in time, simply because if a user can create a pointer, they should be able to directly remove it. It's tidier that way.

When was I required to have reasons, anyway? :D

SUCCESSOR
06-08-2015, 04:43 PM
simply because if a user can create a pointer, they should be able to directly remove it. It's tidier that way.


Pointers aren't ever deleted unless they go out of scope. They just stop pointing to anything, become invalid. C++ allows you to delete a pointer that is invalid or point to null but it doesn't actually do anything. It just doesn't give an error.

ZoriaRPG
06-08-2015, 06:42 PM
I'm not sure what point there is arguing this topic... I never once, used the word 'delete', so now you're just meddling with semantics because you clearly oppose this, for whatever reason.

I don't care if the stack and heap are relieved of the pointer, and data, by release, by remove_pointer; or by delete + set to NULL. I'm not even sure why we're still discussing this, except that you seem to care about it for whatever reason. I'm curious what aspect of this, as a suggestion, is problematic to you, as I can live either way. As long as whatever function used, doesn't conflict with the present remove() method, it shouldn't matter to anyone if the pointer is packing a lunch for a tour of Jupiter.

SUCCESSOR
06-09-2015, 12:19 AM
Whoa, can we not have a civil discussion? Maybe you should take a walk of one of those pills that makes one "chill".

I think the on going problem of this discussion is you mixing up pointers with objects. You can call it semantics but when you are taking about removing pointers you really throw me off. I am not trying to get you all wound up or anything. It truly took me until that last post to realize you meant that you wanted to remove an object and be able to check if it is valid without waiting for the next frame.

I have nothing against it being internalized or changing the way it works or isValid() works so that the results are instantaneous. Then again aren't there several things that you have to wait a frame for?

Instead of writing custom functions you could simply add another condition anytime you check isValid().

if(item->isValid() || item->X == 32768)

if(npc->isValid() || npc->HP == HP_SILENT)

if(eweapon->isValid || eweapon->DeadState == WDS_DEAD)

ZoriaRPG
06-09-2015, 01:24 AM
No worries. I have no problems with debate, or discussion: It just seemed as if you were arguing against a change, that didn't seem rational, whilst simultaneously misrepresenting what I was discussing. I'm not a C++ expert, but I know three valid ways to achieve a satisfactory remove result. As I mentioned, even delete is possible--if you also remember to set the pointer to NULL, unless you want nasty memory leaks--but as you said, it doesn't achieve much, and release would be more appropriate here. I'm reasonably confident that ZC does that now, on its own; but there is no way to instruct that release directly.

I truly don't know what happens to the pointer, on the stack, when it's removed, after a frame, but I believe that the register used by it, is freed at that time, but not before. Unfortunately, unless ZConsole can tell me--pretty sure it cannot--I can't view the stack in real-time to determine what changes. There are a finite number of concurrent pointers available at all times: 256 as I understand; perhaps 255--then again, there are 4095 array pointers, so perhaps other object type pointers / vectors share the same regs as arrays. I've never seen the source, so I simply don't know how it's set up.

Conjecture follows: Until one is released, the register using it is unavailable. If you exceed the number of available regs for pointers, overflows occur. That's pretty much standard, common sense. Nothing I am doing now, could do that, but I see it as a potential event in the future, given some of what I'd like to accomplish. Then again, a far higher priority wish-list item, is declaration of complex datatypes a ta global level (that thread is also here, with explanation of my reasons), because that would make them more useful...and is far more pertinent to what I'm doing at present, than this.

Simultaneously, the data for a pointer is maintained on the heap, as long as that pointer is not directed at NULL. If for some reason, I wish to create, and destroy, 100 objects at a time, with several iterations thereof, in a frame, an internalised remove() would permit that; whereas the present remove, would not. That may sound silly, until you consider that in order to replicate some things that are unnatural to ZC, I would need to define construct objects to set up non-uniform hitboxes. Each of those may contain 20 or more objects (overlapping). if collision occurs, each of those must die at once, and be replaced with 20, smaller objects in a different formation.

Consider replicating vector-graphics objects, such as the asteroids in 'Asteroids', with draw commands. The polygons would be filled, at each line, and point, with very small (invisible) objects, that have a definable hitbox. That would permit creating precise hitboxes for irregular shapes, that can change, rotate, and otherwise be manipulated. We're talking about hitboxes between 1px and 10px in size.

I know ZC was never meant for that, but it is possible. Mass manipulation of things like this, would flow better, if it was possible to deallocate the registers in use.

As to the proposed statements, I make functions to do these things, pretty much in the form of macros. I mean that. I eve have a function NAND(boolA,boolB) , and custom NOR and XOR functions very much the same, plus NAND (int arr) . I'm missing a few complex logic operators that deal with more than two values, but I never object to more functions. It's not as if I have a finite amount of space for them.

Witht he present Remove() functions, Remove(n) already sets HP silent, and moves the enemy to a specific position. Likewise, Remove(l) or Remove(e) move the object to the same coordinates; so by packaging !isValid && coordinates, I can return if a pointer is still in use this frame. I can't deallocate it, but at least I can pass reading it. Remove(f) is one of the few that differs, as I recall, but I have isOnscreen() and isOffScreen functions that I can use as a totality, that include the isValid() function, so I need only make one call to achieve a goal.

This becomes critical, when you have for loops nested 4 to 6 levels deep, running every frame; as optimising them to ignore invalid objects becomes mandatory. Users with high-performance systems won;t notice a difference, but testing that type of compound / nested loop on older hardware truly shows how much of an impact it can have. That said, I likely do need to expand my definitions for object validity of other sorts, do that I can skip them if other conditions also apply (NAND, AND).

The only problem with using all these self-defined functions, is that sharing code becomes impossible without requiring the same resources, or heavily modifying it. I'll usually supply an external header with compatibility functions if people want only specific portions of what I'm using for something else, and let them sort it out if they want to strip it down to essentials. Otherwise, it all goes into the custom engine, and becomes invisible to a user that would want to make the system work out of the box. (I plan to package beta, and later releases, with at least two .qst templates, so that people never need to touch most of the header to make use of it.)