Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Improvement] set_aside multiple items #26

Open
haggys22 opened this issue Jun 18, 2022 · 3 comments
Open

[Improvement] set_aside multiple items #26

haggys22 opened this issue Jun 18, 2022 · 3 comments

Comments

@haggys22
Copy link

I wanted to recreate the crafting process from this video with kalandralang but it seems impossible without setting aside multiple items because it wants to recombine 4 items into 2 and then into 1 one

TL;DR

Using recombinators to combine items A, B, C and D into items AB and CD first, then into ABCD is impossible with only one set_aside slot

Proposal

Implement set_aside as a stack. set_aside pushes the current item on top of the stack. Actions like recombine consume the item on top of the stack.

This still has limitations when creating more complex recipes but allows the use case described above

Alternative

Implement set_aside as a map/dictionary with string keys, so you can name items (set_aside item_name) and consume arbitrary items by referencing their name (recombine item_name, swap item_name_to_receive item_name_to_set_aside)

I reckon this is far more complex to implement but may be considered if recombinators will stay as a core mechanic

Examples (pseudo code)

Stack

Currently set_aside in line 11 would overwrite the item previously set aside in line 7

 1: .base_ab:
 2:   buy "Imbued Wand" with prefix A
 3:   set_aside
 4:   buy "Prophecy Wand" with prefix B
 5:   recombine
 6:   if not prefix A+B goto .base_ab
 7:   set_aside
 8:
 9: .base_ac:
10:   buy "Imbued Wand" with prefix A
11:   set_aside # pushes on set_aside stack
12:   buy "Tornado Wand" with prefix C
13:   recombine # consumes item from line 11
                # item from line 7 is now on top of set_aside stack
14:   if not prefix A+C goto .base_ac
15: 
16: if base type "Imbued Wand" goto .bc
17: swap # sets item from line 7 as current item
          # pushes current item from line 13 on top of set_aside stack
18: if base type "Imbued Wand" goto .bc
19: goto .base_ab # none of both bases is an "Imbued Wand"; restart
20: 
21: .bc:
22:   recombine # consumes item from line 13 (swapped in line 17)
23:   if not (base type "Imbued Wand" and prefix A+B+C) goto .base_ab
24:
25: show # "Imbued Wand" with prefixes A, B and C

Map

 1: .base_ab:
 2:   buy "Imbued Wand" with prefix A
 3:   set_aside item_a
 4:   buy "Prophecy Wand" with prefix B
 5:   recombine item_a # consumes item_a from line 3
 6:   if not prefix A+B goto .base_ab
 7:   set_aside item_ab
 8:
 9: .base_ac:
10:   buy "Imbued Wand" with prefix A
11:   set_aside item_a
12:   buy "Tornado Wand" with prefix C
13:   recombine item_a # consumes item_a from line 11
14:   if not prefix A+C goto .base_ac
15:
16: if base type "Imbued Wand" goto .bc
17: swap item_ab item_ac # sets aside the current item as item_ac
                         # retrieves item_ab from line 7 as the current item
18: if base type "Imbued Wand" goto .bc
19: goto .base_ab
20:
21: .bc:
22:   recombine item_ac # consumes item_ac from line 17
23:   if not (base type "Imbued Wand" and prefix A+B+C) goto .base_ab
24:
25: show # "Imbued Wand" with prefixes A, Band C
haggys22 added a commit to haggys22/kalandralang that referenced this issue Jun 19, 2022
* state.aside is now a list
* set_aside pushes the current item as the head
* with_aside fails if the list is empty; uses head otherwise
* awaken and recombine consume the head of the list
* beastcraft_split pushes the split item as the head of the list
* swap replaces the current item with the head of the list
  * if there is no current item: removes the head of the list, if not empty
  * if the list is empty: sets the current item to None
@doomeer
Copy link
Owner

doomeer commented Jun 19, 2022

See my answer in #29 — short version: yes! It's now in master.

I agree that we may eventually want to name set-aside items. We'll see once we have an example use case where it would really help.

@haggys22
Copy link
Author

I think i came up with a use case for named set-aside items:

When recombining items but you don't get your desired outcome it can often be used as one of the two bases for another try. With named set-aside items I could imagine a predicate whether a set-aside item name exists (e.g. is_set_aside <name>) and an instruction to receive a named set-aside item as the current item (e.g. get_aside <name>) for the following crafting process:

.start:
if is_set_aside "base a" then goto .finished_a
# craft base a
set_aside "base a"
.finished_a:

if is_set_aside "base b" then goto .finished_b
# craft base b
set_aside "base b"
.finished_b:

get_aside "base a"
recombine "base b"
if <desired outcome> then goto .success
if <good enough for base a> then {
  set_aside "base a"
} else {
  if <good enough for base b> then {
    set_aside "base b"
  }
}
goto .start

.success:
# continue crafting

@doomeer
Copy link
Owner

doomeer commented Jun 26, 2022

That's a very good point.

EDIT: I wrote the text bellow without realizing that set-aside already can contain multiple items, and thus are already "pools". In a thread named "set_aside multiple items". I'm tired. I'm leaving the comment anyway 😅

In fact I had an idea a few weeks ago of having "pools" of items. This is basically the same except that there can be more than one item in a pool. The idea is that when recombining, you can often end up with multiples of the same item. For instance let's say you want to make a ring with T1 int and T1 dex. You may spam alterations trying to get each of the T1 attribute mods. But while doing that you will probably see e.g. T1 dex thrice before seeing T1 int. You could toss the additional T1 dex rings away, but that would be suboptimal because if recombination fails you may very well have a use for them later.

If we also had functions, this could look like this:

function categorize {
  if tier "Dexterity" <= 1 then {
    if tier "Intelligence" <= 1 then push "both" else push "dex"
  }
  if tier "Intelligence" <= 1 then push "int" else
    push "base" # note: if item is rare we actually would have to scour and transmute here
}

function get_attribute $pool {
  until not is_empty $pool do {
    if is_empty "base" then buy magic "some ring base" else pop "base"
    alt
    categorize
  }
  pop $pool
}

until not is_empty "both" do {
  get_attribute "int"
  set_aside
  get_attribute "dex"
  recombine
  categorize
}

pop "both"

It's a lot of boilerplate but it can be interesting. Also one could maybe tell Kalandralang to keep pools when repeating recipes to more accurately reflect average cost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants