Is there a way to read a file in to a buffer?

dj_d

Member
I'm specifically interested in reading in a CCS, appending stuff to it, then writing out the results. This may also require me to use a path for file_to_map - is that possible?.

I'll note, though, that I'd find it generally awesome to have:

string_to_file()
file_to_string()
string_to_map()
map_to_string()

(or replace 'string' with 'buffer'). Some of this can be approximated with maps but it'd be handy to be able to do it directly.
 

zarqon

Well-known member
I agree that the second two functions you mentioned could come in handy.

As for the first two, giving mafia filesystem I/O access poses security questions, particularly if you could specify the path. Limiting it to the application directory could work, or certain filetypes/extensions, but given that mafia is user-programmable, the risks probably outweigh the functionality.

As I understand it, you're looking to make an ASH script that modifies your ccs on the fly...? Why not just write a consult script?
 

dj_d

Member
[quote author=zarqon link=topic=2130.msg10892#msg10892 date=1231104976]
As for the first two, giving mafia filesystem I/O access poses security questions, particularly if you could specify the path.

As I understand it, you're looking to make an ASH script that modifies your ccs on the fly...? Why not just write a consult script?
[/quote]

Making it relative to the home directory (and disallowing ../) would probably solve the problem - then the exposure wouldn't be any different than what map_to_file etc do today.

I don't know about you, but I find ccs management to be one of the biggest PITA about mafia! Even something simple... like when I run OCW, I'm always screwing up in GMoB because I have the wrong ccs set (rock band vs. jam band, some specialized ccs, whatever).

I want a script that modifies whatever you're doing right now and/or switches you temporarily out of it and then back, not another ccs to deal with. :)
 

zarqon

Well-known member
I have hard evidence (from hundreds of notify kmails) that many Windows users have KoLmafia sitting on their desktops, or in their My Documents folder.

(Side note: FTF handles the GMOB, pretty smartly if I dare say so myself. You've been using an older version.)

Perhaps a safer alternative would be making your current ccs script available to ASH. Similar to get_property() and set_property(), we could have something like

string[int] get_ccs_category(string category) which returns a map of the ccs category in question.
void set_ccs_category(string category, string[int] commands) which writes a map of commands into your current ccs.

So if your ccs had this:

Code:
[ green ops ]
1: skill noodles
2: skill lunging thrust-smack

Then calling get_ccs_category("green ops") would return a map like so:

[1] => "skill entangling noodles"
[2] => "skill lunging thrust-smack"


And, after doing whatever modifications you wanted to do, you could then write that category back to your ccs using set_ccs_category(). In your GMOB example, let's say you wanted to ensure that you would throw the rock band flyers, not the jam band ones:

Code:
string[int] orders = get_ccs_category("guy made of bees");
if (count(orders) != 0)
  foreach i in orders
   if contains_text(orders[i],"jam band flyers") {
     orders[i] = "item rock band flyers";
     set_ccs_category("guy made of bees",orders);
   }

This might be a nice, safe way to do what you're talking about.

Although, I still think you could just write a consult script. :) Personally, I have only two ccs scripts in my ccs dir and haven't needed more.
 

Alhifar

Member
file_to_string() combined with cli_execute("mirror") would easily allow a mallbot script to be written, for what it's worth.
 

dj_d

Member
I don't think I made the point clear enough... the idea is that I want a script that can dynamically override/update whatever I've set manually (a particular CCS, a consult script, whatever) with settings appropriate to the action it's about to take. I realize I can manually set the CCS to be a consult script that does what I want - the point is that I don't have to remember to do that.

What's the "mirror" command do?
 

Bale

Minion
[quote author=dj_d link=topic=2130.msg10948#msg10948 date=1231318072]
I don't think I made the point clear enough... the idea is that I want a script that can dynamically override/update whatever I've set manually (a particular CCS, a consult script, whatever) with settings appropriate to the action it's about to take. I realize I can manually set the CCS to be a consult script that does what I want - the point is that I don't have to remember to do that. [/quote]

I agree about the usefulness of that. In order to account for all possibilities a lot of different CCS are necessary. I find it annoying how many I have since I can't always remember which is which. It would be nice to have a script capable of creating its own CCS for use in each specific circumstance.

However, I think you're considering the wrong implementation of this. It might be better if a script was capable of simply setting a buffer for use as a CCS while executing the script. That would save all the potential security and mallbot issues attendant in writing the buffer to a file.
 

zarqon

Well-known member
My point is that you could do everything in a single consult script, then not have to worry about changing it, ever. A consult script can essentially become all of your ccs's wrapped into one, with conditionals built in.

(If you weren't already an accomplished scripter, I would not have suggested it. But since you are, writing a consult script can do exactly what you are requesting additional functionality to do.)

For ease of use, however, making the current CCS accessible to ASH would be nice. Then, either a ccs with a consult script in it could reference itself, or you could set a betweenBattleScript that ensures your CCS contains the appropriate directives. But this would be a decision for the devs.
 

dj_d

Member
Z: You're correct (and thank you), but it's sort of inelegant and a PITA to have the logic in two places. For example, if I'm in the kitchen because I want to level up vs. because I want to cast Salve against something that can't kill me I'll use different logic during the fight. My .ASH knows which I mean to do, but my CCS/consult script would have to know which of those I want as well... easier to just have the script pick/modify the CCS on the fly.

I agree that an elegant solution would be to simply let the ASH script read the CCS in to a buffer, and hand back a buffer that could be used as a CCS.

And thanks -had no idea mirror could do that!
 

zarqon

Well-known member
[quote author=dj_d link=topic=2130.msg10966#msg10966 date=1231408749]
My .ASH knows which I mean to do, but my CCS/consult script would have to know which of those I want as well... easier to just have the script pick/modify the CCS on the fly.[/quote]

Since consult scripts are written in ASH, they can figure out what you want to do just as easily as an ASH script which is not a consult script. The picking/modifying can take place in your ASH consult script rather than some external script -- then all the logic is in one place.

You could even have multiple consult scripts containing various combat strategies, and a master consult script which imports the others, decides which strategy you want to use, and calls the appropriate script for your combat.

Then your ONLY ccs would look like this:

[ default ]
consult masterccs.ash


Include set_property("battleAction","custom combat script"); in your login, you never have to remember to change it again.
 

dj_d

Member
I'm clearly not explaining myself very well, but let me try one more time...
If I run GetKitchenFood.ash, I want a different combat action than if I run UseKitchenToHealUpViaSauce.ash. I want the script to specify that, and I want to put it all in the script, rather than have the script swapping between a bunch of ccs files littering up the directory.

On a completely separate note, I'd like to use string/file IO functions for stuff like writing out the results of EatDrink.ash in case it got interrupted (got a feature request for that), making data files that were more flexible (since I would parse them and not just have them read programmatically in to a map), and lots of other neat stuff.

Anyway, pardon my apparant difficulty in conveying what I'm trying to accomplish, but - Jason, ver, et al, what do you think? Specify a buffer to be used in place of the current CCS from a script? File/string IO?
 

zarqon

Well-known member
Oh, now I get it. Sorry for being dense.

Now that I understand what you're wanting to do ... it seems like the only way to do it is manually, similar to the way OCW uses meat vortices against the brigands. But that's definitely more of a PITA than multiple ccs's. So I must agree, it would be nice for scripts to have an easy but dynamic method of telling mafia how to auto-adventure, without sidestepping autoadventuring altogether.

Ooh! Perhaps adventure(int, location, string[int]), where the last variable is a ccs to use (round => action). That would be hot.
 

Bale

Minion
[quote author=zarqon link=topic=2130.msg10988#msg10988 date=1231578676]
Ooh! Perhaps adventure(int, location, string[int]), where the last variable is a ccs to use (round => action). That would be hot.
[/quote]

Something like this?

string [int] ccs1;
ccs1 [1] = "[ default ]"
ccs1 [2] = "0: pick pocket"
ccs1 [3] = "1: attack"
ccs1 [4] = "[ mer-kin scavenger ]"
ccs1 [5] = "0: pick pocket"
ccs1 [6] = "1: olfaction"
ccs1 [7] = "2: default"

A bit cumbersome, but it would be really nice to have.
 

dj_d

Member
@bale: Right, but with one more twist - I could get the current CCS in an array, too (so I could just append to it if desired).
 

Bale

Minion
[quote author=Bale link=topic=2130.msg10989#msg10989 date=1231580394]
string [int] ccs1;
ccs1 [1] = "[ default ]"
ccs1 [2] = "0: pick pocket"
ccs1 [3] = "1: attack"
ccs1 [4] = "[ mer-kin scavenger ]"
ccs1 [5] = "0: pick pocket"
ccs1 [6] = "1: olfaction"
ccs1 [7] = "2: default"
[/quote]

Thinking some more, it might be cleaner if the CCS looked like this:

string [string, int] ccs1;
ccs1 ["default", 0] = "pick pocket"
ccs1 ["default", 1] = "attack"
ccs1 ["mer-kin scavenger", 0] = "pick pocket"
ccs1 ["mer-kin scavenger", 1] = "olfaction"
ccs1 ["mer-kin scavenger", 2] = "default"

That would be easier for an ash to search and modify.
 

zarqon

Well-known member
Thinking about it, a better data type is string[string][int]. First key is category (monster or location), second key is round number, value is action.

EDIT: haha, got ninja'd by Bale. Does this mean we have great minds?
 

Bale

Minion
[quote author=zarqon link=topic=2130.msg10994#msg10994 date=1231581400]
Thinking about it, a better data type is string[string][int]. First key is category (monster or location), second key is round number, value is action.
[/quote]

Agreed! I didn't realize maps could be indexed in that way also.

Code:
string [string] [int] ccs1;
ccs1 ["default"] [0] = "pick pocket"
ccs1 ["default"] [1] = "attack"
ccs1 ["mer-kin scavenger"] [0] = "pick pocket"
ccs1 ["mer-kin scavenger"] [1] = "olfaction"
ccs1 ["mer-kin scavenger"] [2] = "default"

Now we just need for one of the devs to agree to implement adventure(int, location, string[string][int]) :D
 

zarqon

Well-known member
Haha, I'm not entirely sure that they can... I wrote my post before I saw yours... we had basically the same idea, I just wrote mine the way I would write it in PHP for some reason. It may be incorrect syntax in ASH, although a brief CLI test showed no errors. They're functionally equivalent, I think (although I'm curious about how the "contains" operator works with multi-dimensional maps now).

To sum up. I superlove the idea of adding:

string[string,int] current_ccs()
boolean adventure(int, location, string[string,int])


to allow scripts to read the current ccs, modify if needed, and adventure using that modified ccs. A huge timesaver for scripters / clutter reducer for users / both for both.

Example:

Code:
retrieve_item(5, $item[meat vortex]);
string[string, int] myccs = current_ccs();
myccs["brigand",1] = "item meat vortex";
myccs["brigand",2] = "default";
while(adventure(5,$location[themthar hills],myccs))
  retrieve_item(5, $item[meat vortex]);
 

jasonharper

Developer
It seems to me that an override like this would need to be in the form of a consult script, not a CCS. A consult script can trivially do anything a CCS can - but the converse is not true, so once you run into something that can only be done via consult, you're back to needing to access arbitrary files. Also, it looks like the suggested interface would be a pain to use, since in general you're not going to know exactly which monster you're going to encounter - you'd potentially have to modify EVERY section of the CCS if you wanted to preserve any of the user's specified behavior.

So, how does this sound - optional 3rd parameter to adventure() is a string, naming a function with the same signature as the main() of a standalone consult script. It would behave like a "consult" line inserted at the start of each CCS section, so the function could either run the entire battle, or return at some point to let the CCS (or other specified battle action) take over. I'm pretty sure this can reasonably be implemented...
 
Top