Jump to content

File names dependant on existing files


NiGHTMARE

Recommended Posts

For Arcane Remix, I'd like to be able to do the following via WeiDU:

 

1) Check what file names exist beginning with SPWI1 and ending in two numbers and .spl.

2) COPY a file to any one SPWI1xx which doesn't exist (e.g. SPWI109.spl, or if SPWI109.spl already exists, it'll save as SPWI121.spl).

 

Now I know this could be done via a whole mass of ACTION_IF NOT FILE_EXISTS, and there's no such thing as FILE_EXISTS_REGEXP, but I'd still like to think there's a more elegant method :).

Link to comment

This was something I suggested being added as a WeiDU command but was never done. Surely the easiest way is to count the number of rows (using COUNT_2DA_ROWS) in the spell 2da (the one the numbers correspond to) , add one to it and save as a variable. Then C_E ~foo.spl~ ~SPWI1%var%~. You'll need some checks however, that the spell 2da isn't full. I'm not sure what you're gonna do if it is though.

Link to comment

FOR (i = 9; i >= 0; i -= 1) BEGIN
 FOR (j = 9; j >= 0; j -= 1) BEGIN
   SPRINT spellname ~SPWI1%i%%j%.spl~
   PATCH_IF FILE_EXIST_IN_GAME EVALUATE_BUFFER ~%spellname%~ THEN BEGIN
     SPRINT out_name ~%spellname%~
   END
 END
END

COPY_EXISTING ~arcane_remix/spl/some_spl.spl~ ~%out_name%~

 

If you can code breaking out of a loop it'll make this faster.

Note: OcaML language itself, differently from C/C++, cannot break out of a for (or while) loop :)

[being a functional language rather than an imperative / OO one has its downsides too ;) ]

Link to comment

Okay I correct myself, I meant spell.ids (which in theory COUNT_2DA_ROWS should work on), however looking at it, of course it has big fucking gaps in it, so that makes my idea kind of void.

 

Back to your method then. Surely the easiest way to break the loops would be to have an ELSE block that sets i and j to 0, breaking the while condition of the FOR loop and the loop will end.

Link to comment
Okay I correct myself, I meant spell.ids (which in theory COUNT_2DA_ROWS should work on), however looking at it, of course it has big fucking gaps in it, so that makes my idea kind of void.

C_2_R uses Str.split regexp_many_newline_or_cr, meaning that multiple newlines don't count, and spaces don't count.

However, even if you C_2_R on spell.ids [something that will be slower than my cycle, since string functions are usually slow], you'll get a wrong count anyway - unless you somehow removed all non-wizard, non first-level entries.

 

Back to your method then.  Surely the easiest way to break the loops would be to have an ELSE block that sets i and j to 0, breaking the while condition of the FOR loop and the loop will end.

Actually, the easiest way is to count from the grounds up (from i = 0 and j = 0) and then add a break statement - this way, it'll stop at the first empty slot.

 

FOR (i = 0; i <= 9; i += 1) BEGIN
FOR (j = 0; j <= 9; j += 1) BEGIN
  SPRINT spellname ~SPWI1%i%%j%.spl~
  PATCH_IF FILE_EXIST_IN_GAME EVALUATE_BUFFER ~%spellname%~ THEN BEGIN
    SPRINT out_name ~%spellname%~
    j = 10 // manual break statement
    i = 10
  END
END
END

 

Of course, this is hideous. but it'll make do (~20 cycles like this are faster than C_2_R on something as big as spell.ids)

Link to comment

Heh, I was about to say I'd have iterated up instead. Also, I'm not sure what you've written is right. Surely you want to check that the file doesn't exist in game e.g.

 

FOR (i = 0; i <= 9; i += 1) BEGIN
FOR (j = 0; j <= 9; j += 1) BEGIN
 SPRINT spellname ~SPWI1%i%%j%.spl~
 PATCH_IF NOT FILE_EXIST_IN_GAME EVALUATE_BUFFER ~%spellname%~ THEN BEGIN
   j = 10 // manual break statement
   i = 10
 END
END
END

 

Random question: Why did you decide to switch variables at the end? You decide to declare out_name and set it to the value of spellname. Why not stick with spellname?

 

Edit: Better English :)

Link to comment
Heh, I was about to say I'd have iterated up instead.  Also, I'm not sure what you've written is right.  Surely you want to check that the file doesn't exist in game e.g.

 

FOR (i = 0; i <= 9; i += 1) BEGIN
FOR (j = 0; j <= 9; j += 1) BEGIN
 SPRINT spellname ~SPWI1%i%%j%.spl~
 PATCH_IF NOT FILE_EXIST_IN_GAME EVALUATE_BUFFER ~%spellname%~ THEN BEGIN
   j = 10 // manual break statement
   i = 10
 END
END
END

:)

 

Random question: Why do you decided to switch variables at the end?  You decide to declare out_name and set it to the value of spellname.  Why not stick with spellname?

For improved readability and modularity. This is mostly a habit from how I'd do the thing in a real PL - in a c-like fashion (assuming a library function exists_in_game), you'd have the following function:

 

char * get_first_empty_name (char * beginning, char * ending)
{
 int i, j;
 char resource_name [12];
 for (i = 0; i < 10; i++)
 {
   for (j = 0; j < 10; j++)
   {
      sprintf(resource_name,"%s%d%d.%s",beginning,i,j,ending);
      if (! exists_in_game(resource_name)) then return resource_name;
   }
 }
 sprintf(resource_name,"");
 return resource_name;
}

 

and then use it with something like

int main ()
{
[...]
out_name = get_first_empty_name ("SPWI1","SPL");
}

 

besides, WeiDU allocates by default the space for up to 255 variables, meaning that up to that count you aren't losing any memory (you can use more than those - but those'll be slower). ;)

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...