Knuckle Cracker

Creeper World 3 => The Coder's Corner => Topic started by: st00pid_n00b on June 26, 2017, 02:23:44 AM

Title: MapMove.crpl, a tool for editing maps
Post by: st00pid_n00b on June 26, 2017, 02:23:44 AM
Update: Now operates on mouse click, easier to undo. Attachment updated.

This script basically cuts and paste a rectangular area, including terrain, digitalis, walls and units.

It's useful for when you make an elaborate structure but then realize it should be a few coordinates to the left, or when you resize a map but want to recenter it. So it allows for mistakes without starting all over again.

It's inspired from the more elaborate LandCopier.prpl (http://knucklecracker.com/forums/index.php?topic=22591.0) by planetfall (thanks for the help).

This is my first script, I probably used too many variables and didn't take advantage of the stack. I needed some clarity to make up for the lack of familiarity with CRPL. Please let me know if you have any suggestion or remark. :)

If you need to duplicate a structure, the script could easily be modified to just copy terrain without erasing, but units can't be simply duplicated, so I didn't include this option.

Instructions (updated)


Detailled instructions (updated)

For people who know nothing about CRPL, like me a few days ago :)


Title: Re: MapMove.crpl, a tool for editing maps
Post by: GoodMorning on June 26, 2017, 03:28:35 AM
Your code is well structured, with descriptive variables. This is more than I can say for some of us - my code regularly uses stack swaps aplenty and puns for variable names, making it less than readable.

Do note that there's an issue (probably with object pooling) that can cause random carryover of OperateWhilePaused status - dangerous in any script that does not allow for it.

Rather than working on save/load (which makes it hard to undo), I suggest having it work when the mapmaker clicks the Core. OperateWhilePaused is useful here, but you eliminate save/load, and can repeatedly use it more easily...
Title: Re: MapMove.crpl, a tool for editing maps
Post by: st00pid_n00b on June 27, 2017, 12:24:41 AM
Thanks for the remarks!

I'm under the impression that playing with the stack allows for more efficient/concise code at the expense of readability. Maybe it's a question of habit... In fact I've started doing funny stuff using the stack in another script I'm working on.

Also my code seemed hard to read to me because of the reverse polish notation, but I'm kind of getting used to it. (And you should be ashamed to use puns as variable names ;))

Quote from: GoodMorning on June 26, 2017, 03:28:35 AM
Do note that there's an issue (probably with object pooling) that can cause random carryover of OperateWhilePaused status - dangerous in any script that does not allow for it.

What do you mean by that? Can the flag carryover to other scripts?

Quote
Rather than working on save/load (which makes it hard to undo), I suggest having it work when the mapmaker clicks the Core. OperateWhilePaused is useful here, but you eliminate save/load, and can repeatedly use it more easily...

What? You can do that? I didn't find anything in the documentation, how do you execute a script on click? By the way, the script works when unpausing too, which allows undo. But then there is the cleanup of delete creeper/digitalis, reset time, and remake the spore towers that have started building.

I have another question concerning the script: I'm making big lists with AppendToList, and I wonder if CRPL stores lists internally as chained lists or arrays. If it's the latter, it would be better to create a big list with an initial size, and use SetListElement.
Title: Re: MapMove.crpl, a tool for editing maps
Post by: GoodMorning on June 27, 2017, 01:10:46 AM
For executing on click, you can use something like the following:

0 GetMouseButtonDown if
GetMouseCell CurrentCoords Distance 1.5 lt if
#Functionality
endif
endif


It is an efficiency/readability trade-off, but you're already using SetTerrain over potentially hundreds or thousands of cells (each such call requires a milliseconds-long GPU texture push). Readability is usually considered the first goal, and it's much easier to sacrifice later than the other way around. Speaking of efficiency, there is CreateListStartingSize, but I do not know what the efficiency gain is. It is quite possible that it depends on the underlying C# library.

OperateWhilePaused can carry over between Cores or scripts, but such is rare enough that it's not major (see some of the early Sleeper maps, however, for a situation in which it is sometimes tactically relevant).
Title: Re: MapMove.crpl, a tool for editing maps
Post by: st00pid_n00b on June 29, 2017, 02:44:29 AM
Ok I was confused because to check for mouse buttons, the script has to be running in the first place... I now understand that a script with OperateWhilePaused status starts running when you close the editor panel. In fact, I realized the script I posted works this way too, no need to save/reload.

However, waiting for a mouse click might be better as you suggested. I'll change that and update the original post.

For the lists, I don't know C# but it seems to have 2 types of lists: LinkedList<T> and List<T>.
The latter is based on an array, that doubles its size when it needs to reallocate. After some testing, it appears CRPL uses the array-based list, which give the computational complexities:

Constant O(1): GetListCount GetListElement SetListElement
Amortized constant O(1): AppendToList
Linear O(n): PrependToList InsertListElement* RemoveListElement*
(* Constant time if at the end of list)

Sorry, I have some background in CS, I couldn't help it :)

For example, doing 100000 times the following instructions gave me the execution times:
SetListElement 78 ms
AppendToList 68 ms
PrependToList 3080 ms
GetListElement 97 ms

In conclusion, using CreateListStartingSize and SetListElement  doesn't give efficiency gains over AppendToList, it even seems slower for some reason. When optimization is necessary, focus should be on the linear time functions (that is, the functions that need to shift the elements in the array).
Title: Re: MapMove.crpl, a tool for editing maps
Post by: GoodMorning on June 29, 2017, 04:41:59 AM
I'm glad I could interest you. It would seem that CreateListStartingSize would preallocate memory (i.e. the appropriate size of array), and changing elements would remain constant-time. So the difference may not be that great.
Title: Re: MapMove.crpl, a tool for editing maps
Post by: st00pid_n00b on June 29, 2017, 03:34:29 PM
Yes, maybe I wasn't clear but I compared CreateListStartingSize+SetListElement  with AppendToList , and there's no performance gain. So CreateListStartingSize is only usefull if you don't fill the list in order.

So I updated the original post, using your code for mouse click. It's still necessary to save/reload to call the awake function and set OperateWhilePaused though (unless I missed something?)

About the Sleeper map bug you mentioned, yes I remember it building digitalis while paused. I've set OperateWhilePaused to FALSE in the destroyed function, which seems to get rid of this bug.

(Note: All I wanted was to recenter a map... How did I end up testing the complexity of C# lists functions? Damn this took too much time...)
Title: Re: MapMove.crpl, a tool for editing maps
Post by: GoodMorning on June 29, 2017, 08:32:10 PM
It happens to us all. If we have any kind of spare time. The term "rabbit hole" is often used.

If you are unwilling to advance one frame while paused, then yes, save/load is required.

That is about all I would/could do, either.