Knuckle Cracker

Creeper World 3 => The Coder's Corner => Topic started by: st00pid_n00b on July 08, 2017, 01:28:58 PM

Title: Some CRPL questions
Post by: st00pid_n00b on July 08, 2017, 01:28:58 PM

Any help is appreciated! I'm mostly concerned about points #1 and #6.

Edit: Save file attached. Use keyboard arrows for control.
It's still work in progress. The functionality and gameplay is there, so that's where I would like feedback / bug reports. It looks bland, I still need to work on the cosmetics and layout, make a proper intro and give info on scoring.
Title: Re: Some CRPL questions
Post by: planetfall on July 08, 2017, 02:49:21 PM
Quote from: st00pid_n00b on July 08, 2017, 01:28:58 PM
I'm writing a script with lots of list manipulations, and was wondering about memory leaks. Are the lists deleted when no variable references them anymore? Does using "--list_name" erase the list or just unassigns the variable? For instance if I have a list L and do:
--L
CreateList ->L

What happens to the old list? What if the old list is referenced by another variable? I don't mean a CopyList, but something like <-L ->L2 before the above code, can I still safely use L2 after that?

I did a small test of this the other day (and ran the game out of memory by creating a 9999999 element list - don't do that) - it seems that lists are properly garbage-collected.

--list only removes that reference to the list. Other references to the list will still work.

Note that when you save the game, list variables are stored by value. If you do the following:


"This is a sentence with words in, innit?" " " Split ->List1
<-List1 ->List2


manipulations to List1 will also affect List2 because they are two references to the same list. If you save and reload, List1 and List2 will have the same contents, but will reference two different lists. The solution is to have one version of the list that is the "master" version. Any other references to this list should be NotPersisted (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:notpersist) and then grabbed from the master using :awake or :gameloaded.

Incidentally - if you need multiple cores to communicate frequently, use lists. G/SetListElement is vastly more efficient than G/SetScriptVar.

QuoteThe documentation (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunitattribute#unit_constants) says that CONST_ISBUILDING can only be set on CRPL towers. I've set it without problems on regular units. Any side effect?

This is vastly outdated information.
I've had some glitches setting it on air units, in which case the launch pad finishes building but the plane doesn't spawn. This was years ago and I haven't tested again in the interim. Setting CONST_ISBUILDING is fine for the vast majority of units.

QuoteIt seems the stack is erased between each script call, but not on Delay. Is that correct? I didn't find it in the documentation.

This is correct.
If you are using Delay, be aware of its limitations. (http://knucklecracker.com/forums/index.php?topic=16703.msg120913#msg120913)

QuoteI tried to set a custom score that doesn't depend on time. What I ended up with in my game over function is:

# Setting the time to 1 frame displays 0:00.0 in the score chart, and gives a base score of 9999.
# (Setting the time to 0 frames doesn't allow to post score.)
1 SetGameTimeFrames
# Compensate for the score related to time, so that only the actual game score is shown.
# (Note: if the score falls to 0 with this method, it won't allow to post,
# but this script can't give a score of 0.)
-9999 AddAdditionalScore
# End the game
0 DestroyAllEnemyUnits

I also came across this map (http://knucklecracker.com/forums/index.php?topic=18393) that handles it differently: it sets the time to the maximum possible to give a base score of 0 (when I tried it gave me instead a leftover score of 63 or something like that).

Are the 0 time and 0 score bugs? I guess the 0 time not allowing to post is to prevent autowin maps. Any suggestions?


This is an area of CRPL I have very little experience with, and that has seen relatively little use by others to boot. Someone else will have to help with this one.

QuoteAny tips to prevent complex scripts from turning into spaghetti code? The main problem is the lack of local variables in functions. This is not meant as a criticism of CRPL, I know it's just an ad-hoc small scripting language. What I did so far:

* Favor stack manipulation hackery over 'local' variables in small helper functions.

* Split into several scripts when possible.

* Maybe prefix 'local' variables with the function name.


To quote an Ancestor of mine: We are chained here forever, you and I, in Colonial Space. Free yourself, run the script and embrace the ineffable spaghetti coder that lives within us all.

QuoteIs someone willing to playtest my map? It's heavily scripted and I mostly want to test for bugs. I don't know if I post it in this thread or make another one in Custom Map Discussion.

Posting here is fine, especially if it's the scripts that need testing. I can't guarantee I'll get to it soon, but someone will.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 08, 2017, 04:45:17 PM
Thanks for the quick and thorough answer! I understand much better now.

Quote from: planetfall on July 08, 2017, 02:49:21 PM
If you save and reload, List1 and List2 will have the same contents, but will reference two different lists

Wow, good to know. I haven't tested much with save and reload, so this needs to be addressed.

QuoteIncidentally - if you need multiple cores to communicate frequently, use lists. G/SetListElement is vastly more efficient than G/SetScriptVar.

Nice, I didn't think about that. So you just use SetScriptVar once to copy a reference to a list? I suppose there is the same issue you mentioned about the lists being duplicated on save/reload?

QuoteIf you are using Delay, be aware of its limitations. (http://knucklecracker.com/forums/index.php?topic=16703.msg120913#msg120913)

Damn, I've definitely used Delay for animations in for loops. Time for more spaghetti... In last resort I can use your hack of defining the awake function in a separate script (wait... is awake per core, not per script?)

I did a small test, and the whole stack is emptied after a save/reload. If inside a loop, it says "loop stack vars not present". Incidentally, if I Trace "I" after the reload (or outside a loop) it just seems to freeze the script with no error message.

QuoteTo quote an Ancestor of mine: We are chained here forever, you and I, in Colonial Space. Free yourself, run the script and embrace the ineffable spaghetti coder that lives within us all.

Haha this was my fourth option :)

The parts I didn't quote were informative too, I just had nothing to add except thanks!
Title: Re: Some CRPL questions
Post by: planetfall on July 08, 2017, 05:19:37 PM
Quote from: st00pid_n00b on July 08, 2017, 04:45:17 PM
Nice, I didn't think about that. So you just use SetScriptVar once to copy a reference to a list? I suppose there is the same issue you mentioned about the lists being duplicated on save/reload?

Yes, both your assumptions are correct.

Quote
Damn, I've definitely used Delay for animations in for loops. Time for more spaghetti... In last resort I can use your hack of defining the awake function in a separate script (wait... is awake per core, not per script?)

I'm unsure what you mean here. Each script can have an :awake; on a core with multiple scripts, every script's :awake will run when the core is initialized.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 08, 2017, 06:08:58 PM
Quote from: planetfall on July 08, 2017, 05:19:37 PM
I'm unsure what you mean here. Each script can have an :awake; on a core with multiple scripts, every script's :awake will run when the core is initialized.

In the thread you linked you wrote:

Quote
What if I put the awake function in a separate script?
Title: Re: Some CRPL questions
Post by: planetfall on July 08, 2017, 06:13:02 PM
Quote from: st00pid_n00b on July 08, 2017, 06:08:58 PM
Quote from: planetfall on July 08, 2017, 05:19:37 PM
I'm unsure what you mean here. Each script can have an :awake; on a core with multiple scripts, every script's :awake will run when the core is initialized.

In the thread you linked you wrote:

Quote
What if I put the awake function in a separate script?


This was with regard to OperateWhilePaused. I was unsure whether enabling OWP on one script meant only that script would operate while paused, or the entire core. (It's only the one script.)
Title: Re: Some CRPL questions
Post by: GoodMorning on July 08, 2017, 06:41:16 PM
With regard to scoring, I have found it more effective to just let it be - it confuses people otherwise. If you are doing a completely different game, then time-to-win is still usually an effective measure.

Regarding spaghetti, planetfall gives sound advice. Also of note is that stack hackery is required only if you want something recursive. Otherwise, a variable used only in that function is preferable for readability and has no real cost except in the most oft-run code. By which I mean hundreds-of-times-per-frame. If you write, then optimise, things are easier to read, change and debug.

Remember, though, that the natural state of things is chaos. Entropy always rises.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 10, 2017, 12:58:42 AM
I updated the original post and attached the map. If someone can test it and see if they can break the script it would be great!

planetfall:
Thanks for the clarification. I got rid of Delays in loops (or anywhere the stack is not empty). Animation speed issues made me realize something strange: 1 Delay is 2 game frames, and n Delay is n+1 frames. It seems like a bug...

GoodMorning:
Yes, it's a different game, in the same vein as the Space Creepers I linked earlier.
I completely agree about readability (premature optimization etc). I was mentioning ways to avoid name clash (unwillingly modify a variable that is used elsewhere). I don't think spaghetti refers to readability, it's about code that's so intermingled that when you try to change something there are side effects everywhere.
Entropy might rise, but not always at the same rate. I'll do what I can to delay the heat death of the universe :)
Title: Re: Some CRPL questions
Post by: planetfall on July 10, 2017, 11:14:00 PM
Some thoughts:
-No bugs found.
-Lack of a hard drop is annoying, holding the down arrow means I usually end up moving the next piece a bit as well.
-Early speed gains seem a bit too small, later they seem a bit fast.
-Harder than normal to line up crops because units aren't visually square
-Since when are combos a thing? Also, most versions have points for drops but not for placement.
-Pausing doesn't seem to be in the spirit of the game.
-Either the pieces are rotating the wrong way, or I'm very rusty.
- http://knucklecracker.com/wiki/doku.php?id=crpl:docs:enablenormalzoomcontrol
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 11, 2017, 11:09:43 PM
Quote from: planetfall on July 10, 2017, 11:14:00 PM
-No bugs found.
Ok, nice!

Quote
-Lack of a hard drop is annoying, holding the down arrow means I usually end up moving the next piece a bit as well.
Ok I can add that. I prefer soft drop but why not both.

Quote
-Early speed gains seem a bit too small, later they seem a bit fast.
I notice them more around level 7-8 but it probably depends on the player ability: each level decreases the vertical timer by 20%. The timers are:
30, 24, 19, 15, 12, 10, 8, 6, 5, 4. Since the last changes are only -1 I don't really see a way around that...

Quote
-Harder than normal to line up crops because units aren't visually square
Yep, and also without a background grid. But visually, a background void looks better than some checkerboard pattern. That's also why I hadn't included hard drop.

Quote
-Since when are combos a thing? Also, most versions have points for drops but not for placement.
I didn't know combos either but found about them while searching for scoring methods. See here for example. (http://www.tetrisfriends.com/help/tips_appendix.php#comboscorechart) It's interesting because it allows for different strategies, setting up for combos is nor the same as for a tetris.

I see points for both drops and placement in other versions. I didn't find how to score drops, should it depend on the height?

Quote
-Pausing doesn't seem to be in the spirit of the game.
Hmm I think most versions allow pause but hide the screen. The pause button isn't disabled with EnableAlternateControlMode anyway, so I put back the P key as well.

There was a funny story with a machine learning algorithm that learned how to play games without prior knowledge. With tetris it didn't figure out it should make lines, so it dropped the pieces as fast as possible to increase the score and when they reached the top paused the game to avoid losing...

A related game spirit concern is save/load: I decided against changing the random seed on load, so the player can know in advance the pieces but he can't reload until he gets the piece he's waiting for.

Quote
-Either the pieces are rotating the wrong way, or I'm very rusty.
Ok, will fix.

Quote
- http://knucklecracker.com/wiki/doku.php?id=crpl:docs:enablenormalzoomcontrol
I was reluctant to use this because the result depends (I guess?) on the screen definition.

A couple more gameplay thoughts:

- I'm not sure about the starting orientation and center of rotation of the pieces.
- Are the sounds annoying?
- Level 10 speed is not indefinitely sustainable for me, but some tetris players are scary, I wonder if the difficulty should keep increasing somehow.
Title: Re: Some CRPL questions
Post by: GoodMorning on July 11, 2017, 11:26:53 PM
Notes: You don't have to drop after a fixed delay. Keeping a float timer allows you to drop after a number of frames on average.


once
    0 @AdjustSpeed
    0 ->DropTimer
    1 ->Threshold
endonce

<-DropTimer <-Speed add ->DropTimer
<-DropTimer <-Threshold gt if
    <-DropTimer <-Threshold sub ->DropTimer
else
    return
endif

#Drop

:AdjustSpeed #[ Level - ]
    1.05 swap pow 0.05 mul ->Speed


Also see Meso for an example of adding Cores to a map for the sole purpose of carrying images. You could apply this to make a background grid.

Edit:
I didn't think I had played Tetris of any form enough to be bothered by a reversed rotation direction - but once the speed was sufficiently high, I more than noticed it.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 12, 2017, 07:01:31 PM
Yes, I can use floats, I will test and see if it doesn't make a jerky movement.

About the image grid, I'll test if it's not too ugly. Kinda defeats the purpose of making tetris with CW3 graphics though.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 16, 2017, 11:13:37 PM
Updated map attached. Changes:

_ nicer looking map
_ hard drop
_ soft drop stops at new tetromino
_ background grid
_ clockwise rotation
_ display combo points
_ display line points
_ info button
_ sound on/off button
_ grid on/off button
_ points for drop
_ float timer and slower speed increase
_ set starting zoom but not disable zoom control (didn't look right when I changed my screen resolution)

I'll upload in a couple of days if there's no other suggestion or bug.
Title: Re: Some CRPL questions
Post by: Builder17 on July 17, 2017, 02:56:30 AM
Not bad, but how Planetfall and GoodMorning have so big scores? :O
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 17, 2017, 05:12:57 AM
Oooh I didn't know the scores were shared for maps outside of colonial space! This mean I "polluted" the server when I did many tests for the score...

There, I beat them, the question is rather why is yours so low?  ;)

I don't know if the scoreboard is also the same when the map is uploaded, but either way don't bother about it because I've got some cleanup to do and there's debug code lying around so the map id won't be the same.
Title: Re: Some CRPL questions
Post by: GoodMorning on July 17, 2017, 06:19:14 AM
Scores are stored on the server by map GUID, which all maps possess. So scores can be submitted and compared for WIP maps as much as for any other - although scores will not be preserved across map changes. If the map (or a save thereof) is opened in the editor, the GUID changes.

Submitting the score is not necessary in order to view it. Note that (unless it is possible to re-sort the score table based on actual score, something I haven't been interested in) the table is sorted by time, then by submission order.
Title: Re: Some CRPL questions
Post by: st00pid_n00b on July 18, 2017, 12:12:36 AM
I know it's not necessary to submit, I wanted to check if it was also displayed correctly in the score chart. Oh well...

You can order the chart by score too. I think I read somewhere it's a global setting so remember to change it back after.