Lua rc scripting: Ending a turn?


Questions, Explanations, Howtos

arc

Temple Termagant

Posts: 8

Joined: Thursday, 16th August 2018, 01:50

Post Thursday, 16th August 2018, 02:40

Lua rc scripting: Ending a turn?

Hello all. I've started playing with the RC lua scripting and I've noticed that while crawl.sendkeys seems to work as i'd guess (also seemingly ignoring user macros) things like crawl.do_commands and food.eat don't seem to work the way i'd expect.

Specifically, the do_commands and food.eat seem to start the action but not finish it (advance a "turn", you.turn_is_over() returns true and attempting other actions that take game time result in errors.). Is there any way other than returning from the function to advance that turn? I can't seem to find one.

Thanks!
User avatar

Zot Zealot

Posts: 982

Joined: Monday, 29th September 2014, 09:04

Post Thursday, 16th August 2018, 04:25

Re: Lua rc scripting: Ending a turn?

Why don't you want to return from the function? Is it because you are trying to store state across multiple turns?

arc

Temple Termagant

Posts: 8

Joined: Thursday, 16th August 2018, 01:50

Post Thursday, 16th August 2018, 04:50

Re: Lua rc scripting: Ending a turn?

chequers wrote:Why don't you want to return from the function? Is it because you are trying to store state across multiple turns?


well one example is i want to do the action, check the result, and then do another action based on that.

a simple example would be look for a corpse, butcher it, <wait game time for butcher to finish>, pick up chunks.

or what if i just want to walk right,right,up,right.

I did notice there's a ready hook. do people often save state in there and then call one action per ready call? Is there a way to play nice with other peoples scripts in that case? It looks like people often use ready to call a function that does "ready stuff" for individual scripts. But what if two scripts try and do an action in the same ready call?

Ideally i'd just like to keep control while my function takes multiple turns.

Slime Squisher

Posts: 344

Joined: Tuesday, 14th April 2015, 19:56

Location: France

Post Thursday, 16th August 2018, 05:10

Re: Lua rc scripting: Ending a turn?

I could see a system using an action queue in ready() :
  Code:
if action queue is empty:
  -- do some checks that put some actions in the queue, like check a global variable do_butcher_corpse
else
  -- pop the first item in the action queue, map it to a function and do that function (like food.eat, or crawl.do_commands
3 runes : MiMo^Ru, HOFi^Beogh, TrMo^Yredelemnul, GrFi^Ru, FoFi^Gozag, MiGl^Okawaru
4 runes : DDFi^Makhleb
5 runes : GrEE^Vehumet
15 runes : MiFi^Ru, NaWz^Sif Muna, GrWz^Sif Muna
I mostly play offline or online on CXC

Dungeon Master

Posts: 388

Joined: Monday, 18th August 2014, 20:04

Post Thursday, 16th August 2018, 18:51

Re: Lua rc scripting: Ending a turn?

If I understand what you're asking for, there is currently no way to do what you're asking. That is, there is no way to trigger time passing on lua script line n (via input or lua api) and return control to line n+1 on your next turn. Right now what you need to do is think of building a state machine with ready() as a sort of controller; save state in a global variable and use a conditional on state in ready() to queue up the next command and state change. If you want to integrate multiple scripts, the simplest thing to try is to write a custom ready() that calls both of the (renamed) ready() functions from the two scripts, in some order -- though this won't work in general if they both try to react to the same cases. Most complicated scripts already have a pretty simple and templatic ready() so it may be easier to integrate their contents directly.

FWIW sendkeys can send multiple keys in succession but all it does is load up the macro buffer; it doesn't hand over control to crawl until your lua code finishes, and then ready() gets call again after everything is processed. This took me a long time to get my head around.

I've looked into implementing something like what you are asking, and I may work on it in the 0.23 cycle as it'd be extremely useful for writing unit tests for UI elements, but it's technically very non-trivial.

Ziggurat Zagger

Posts: 6454

Joined: Tuesday, 30th October 2012, 19:06

Post Thursday, 16th August 2018, 19:33

Re: Lua rc scripting: Ending a turn?

You'd want something analogous to promises/async frameworks. You could roll your own in LUA to accomplish this (in the manner fingolfin suggests) but restoring your state and resuming execution isn't really very trivial if you wanted to generalize it sufficiently. However since funcitons in LUA are first class values, you can at least do something reasonable like make a table of functions and store a list of actions that refer to the table (that's probably how I would implement in LUA)
Spoiler: show
This high quality signature has been hidden for your protection. To unlock it's secret, send 3 easy payments of $9.99 to me, by way of your nearest theta band or ley line. Complete your transmission by midnight tonight for a special free gift!

Ziggurat Zagger

Posts: 6454

Joined: Tuesday, 30th October 2012, 19:06

Post Thursday, 16th August 2018, 19:38

Re: Lua rc scripting: Ending a turn?

Now that I think about it for another minute or two, for this kind of purpose you could just implement a .then (promise-style) object, no action table required, each .then would just reference the next action in the chain, and ready() would just pop off the top of the stack and execute it (effectively you'd have a linked list of objects)

State (such as it would be needed) could be passed down the object chain in a table removing the need for any globals except a single head promise object for ready() to pop.
Spoiler: show
This high quality signature has been hidden for your protection. To unlock it's secret, send 3 easy payments of $9.99 to me, by way of your nearest theta band or ley line. Complete your transmission by midnight tonight for a special free gift!

arc

Temple Termagant

Posts: 8

Joined: Thursday, 16th August 2018, 01:50

Post Friday, 17th August 2018, 04:53

Re: Lua rc scripting: Ending a turn?

Thanks for the info/ideas guys and thanks advil for the clarification of what's going on.

I think I can get what i need out of the scripts now :)

Dungeon Master

Posts: 250

Joined: Thursday, 27th November 2014, 19:12

Post Tuesday, 21st August 2018, 15:35

Re: Lua rc scripting: Ending a turn?

What you want to do is instead of using ready() directly is have ready() add a macro using the api (crawl macros are Lua coroutines) and then execute that macro.

Instead of your macro being a usual ^D entered macro, it should be a coroutine you write in Lua, that does the command you're interested in and then calls yield(). Crawl will do the command, let the world react, and then re-enter your macro coroutine after the yield() call. State can be kept in the function body as usual.

There's some more magic you need to do regarding delay interrupts that I don't really know in detail and is a gap in the api documentation I prepared.

Dungeon Master

Posts: 250

Joined: Thursday, 27th November 2014, 19:12

Post Tuesday, 21st August 2018, 16:01

Re: Lua rc scripting: Ending a turn?

After talking to advil about this on IRC... this could cause crawl to crash if you use the wrong parts of the api from your coroutine. Good luck!

arc

Temple Termagant

Posts: 8

Joined: Thursday, 16th August 2018, 01:50

Post Thursday, 23rd August 2018, 03:46

Re: Lua rc scripting: Ending a turn?

Ah interesting okay. and how does one add a macro? I see a runmacro() function but no functionality to add them. Are all global lua functions eligible to be called as macros?

Is there a category of calls that may crash?

Return to Coding

Who is online

Users browsing this forum: No registered users and 5 guests

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.