Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

- Added the `cannot_modify_cost` tag for patterns that should ignore the `media_consumption` attribute when calculating cost, by Robotgiggle in [987](https://github.com/FallingColors/HexMod/pull/987).
- Added Meditation and Recollection for advanced pattern-list creation, by Robotgiggle in [#1046](https://github.com/FallingColors/HexMod/pull/1046).

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
public final class SpecialPatterns {
public static final HexPattern INTROSPECTION = HexPattern.fromAngles("qqq", HexDir.WEST);
public static final HexPattern RETROSPECTION = HexPattern.fromAngles("eee", HexDir.EAST);
public static final HexPattern MEDITATION = HexPattern.fromAngles("eqqqe", HexDir.SOUTH_WEST);
public static final HexPattern RECOLLECTION = HexPattern.fromAngles("qeeeq", HexDir.SOUTH_EAST);
public static final HexPattern CONSIDERATION = HexPattern.fromAngles("qqqaw", HexDir.WEST);

public static final HexPattern EVANITION = HexPattern.fromAngles("eeedw", HexDir.EAST);
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package at.petrak.hexcasting.api.casting.eval.vm

import at.petrak.hexcasting.api.HexAPI
import at.petrak.hexcasting.api.casting.PatternShapeMatch.*
import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.casting.eval.*
import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota
import at.petrak.hexcasting.api.casting.getPositiveInt
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.IotaType
import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.casting.iota.DoubleIota
import at.petrak.hexcasting.api.casting.iota.PatternIota
import at.petrak.hexcasting.api.casting.math.HexDir
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.casting.mishaps.*
import at.petrak.hexcasting.api.utils.*
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerLevel
Expand Down Expand Up @@ -113,8 +113,9 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
this.handleParentheses(iota)?.let { (data, resolutionType) ->
return@executeInner CastResult(iota, continuation, data, listOf(), resolutionType, HexEvalSounds.NORMAL_EXECUTE)
}
} catch (e: MishapTooManyCloseParens) {
} catch (e: Mishap) {
// This is ridiculous and needs to be fixed
val pattern = (iota as? PatternIota)?.pattern
return CastResult(
iota,
continuation,
Expand All @@ -123,8 +124,12 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
OperatorSideEffect.DoMishap(
e,
Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
HexAPI.instance().getRawHookI18n(HexAPI.modLoc("close_paren"))
pattern ?: HexPattern(HexDir.WEST),
HexAPI.instance().getRawHookI18n(HexAPI.modLoc(when (pattern?.angles) {
SpecialPatterns.RETROSPECTION.angles -> "close_paren"
SpecialPatterns.MEDITATION.angles -> "open_n_parens"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meditation never throws now, so I think this part should be removed (correct me if I'm wrong)

Copy link
Copy Markdown
Member Author

@Robotgiggle Robotgiggle May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still throws if you cast it without the proper number argument (see lines 310 and 311)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ic

else -> "unknown"
}))
)
)
),
Expand Down Expand Up @@ -177,7 +182,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
* Return a non-null value if we handled this in some sort of parenthesey way,
* either escaping it onto the stack or changing the parenthese-handling state.
*/
@Throws(MishapTooManyCloseParens::class)
@Throws(Mishap::class)
private fun handleParentheses(iota: Iota): Pair<CastingImage, ResolvedPatternType>? {
val sig = (iota as? PatternIota)?.pattern?.angles

Expand Down Expand Up @@ -246,6 +251,25 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
}
}

// Meditation is treated as a normal pattern while nested since there's
// no way to determine how many layers it should open
//
// SpecialPatterns.MEDITATION.angles -> {
// throw MishapTooManyCloseParens()
// }

SpecialPatterns.RECOLLECTION.angles -> {
displayDepth = 0
val newStack = this.image.stack.toMutableList()
newStack.add(DoubleIota(this.image.parenCount.toDouble()))
newStack.add(ListIota(this.image.parenthesized.toList().map { it.iota }))
this.image.copy(
stack = newStack,
parenCount = 0,
parenthesized = listOf()
) to ResolvedPatternType.EVALUATED
}

else -> {
val newParens = this.image.parenthesized.toMutableList()
newParens.add(ParenthesizedIota(iota, false))
Expand Down Expand Up @@ -280,6 +304,23 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
throw MishapTooManyCloseParens()
}

SpecialPatterns.MEDITATION.angles -> {
val newStack = this.image.stack.toMutableList()
val layers = when (val topIota = newStack.removeLastOrNull()) {
null -> throw MishapNotEnoughArgs(1, 0)
else -> listOf(topIota).getPositiveInt(0)
}

this.image.copy(
stack = newStack,
parenCount = this.image.parenCount + layers
) to ResolvedPatternType.EVALUATED
}

SpecialPatterns.RECOLLECTION.angles -> {
throw MishapTooManyCloseParens()
}

else -> {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,8 +990,11 @@
"rawhook.hexcasting:": {
open_paren: "Introspection",
close_paren: "Retrospection",
open_n_parens: "Meditation",
close_all_parens: "Recollection",
escape: "Consideration",
undo: "Evanition",
unknown: "Unknown Pattern (this is a bug!)",
},

"iota.hexcasting:": {
Expand Down Expand Up @@ -1960,19 +1963,23 @@

patterns_as_iotas: {
"1": "One of the many peculiarities of this art is that $(italic)patterns themselves/$ can act as iotas-- I can even put them onto my stack when casting.$(br2)This raises a fairly obvious question: how do I express them? If I simply drew a pattern, it would hardly tell Nature to add it to my stack-- rather, it would simply be matched to an action.",
"2": "Fortunately, Nature has provided me with a set of $(l:casting/influences)influences/$ that I can use to work with patterns directly.$(br2)In short, $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ lets me add one pattern to the stack, and $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ let me add a whole list.",
"2": "Fortunately, Nature has provided me with a set of $(l:casting/influences)influences/$ that I can use to work with patterns directly.$(br2)To summarize, $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ lets me add one pattern to the stack, $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ let me add a whole list, $(l:patterns/patterns_as_iotas#hexcasting:open_n_parens)$(action)Meditation/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_all_parens)$(action)Recollection/$ allow for more advanced list creation, and $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Evanition/$ lets me undo mistakes made with the others.",
escape: {
"1": "To use $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$, I draw it, then another arbitrary pattern. That second pattern is added to the stack.",
"2": "One may find it helpful to think of this as \"escaping\" the pattern onto the stack, if they happen to be familiar with the science of computers.$(br2)The usual use for this is to copy the pattern to a $(l:items/scroll)$(item)Scroll/$ or $(l:items/slate)$(item)Slate/$ using $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$, and then perhaps decorating with them.",
},
parens: {
"1": "Drawing $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ makes my drawing of patterns act differently, for a time. Until I draw $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Retrospection/$, the patterns I draw are saved. Then, when I draw $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$, they are added to the stack as a list iota.",
"1": "Drawing $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ makes my drawing of patterns act differently, for a time. Until I draw $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$, the patterns I draw are saved. Then, when I draw $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$, they are added to the stack as a list iota.",
"2": "If I draw another $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Introspection/$, it'll still be saved to the list, but I'll then have to draw $(italic)two/$ $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospections/$ to get back to normal casting.",
},
advanced_parens: {
"1": "Removes a number from the stack, then acts as though I'd drawn that many $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspections/$. Treated as a normal pattern while $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)introspecting/$, so nesting this may require $(l:patterns/patterns_as_iotas#further_notes)$(action)tricks/$ to draw extra $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospections/$.",
"2": "Works like $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$, but closes $(italic)all/$ open $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspections/$ at once. The number of layers closed, along with the list of saved patterns, are then added to the stack.",
},
undo: "Finally, if I make a mistake while drawing patterns inside $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Intro-/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ I can draw $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Evanition/$ to remove the last pattern that I drew from the pattern list that is being constructed.",
further_notes: {
title: "Further Notes",
"1": "I can escape the special behavior of $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Intro-/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ by drawing a $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ before them, which will simply add them to the list without affecting which the number of $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospections/$ I need to return to casting.$(br2)If I draw two $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Considerations/$ in a row while $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)introspecting/$, it will add a single $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ to the list.",
"1": "I can escape the special behavior of patterns like $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Intro-/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ by drawing a $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ before them, which will simply add them to the list without affecting which the number of $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospections/$ I need to return to casting.$(br2)If I draw two $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Considerations/$ in a row while $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)introspecting/$, it will add a single $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ to the list.",
"2": "If an iota other than a pattern is present in a list to be executed by $(l:patterns/meta#hexcasting:eval)$(action)Hermes' Gambit/$ or any other meta-evaluation pattern, it will normally result in a mishap. However, this can be avoided using the patterns described in this section.$(br2)Just as with pattern iotas, the patterns described here can be used to \"escape\" $(o)any other$() kind of iota, causing it to be pushed to the stack when something tries to evaluate it instead of causing a mishap.",
"3": "This technique may be useful if I want a _Hex to be able to reference a specific iota, such as a complicated vector or an entity reference, without having to construct or obtain it each time.$(br2)The process of getting such an iota into a list of patterns in the first place may be somewhat involved. The simplest method would be to draw a placeholder pattern when assembling the list, and then make use of $(l:patterns/lists#hexcasting:replace)$(action)Surgeon's Exaltation/$ to replace it with my desired iota.",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,28 @@
"signature": "eee"
}
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.rawhook.hexcasting:open_n_parens",
"anchor": "hexcasting:open_n_parens",
"text": "hexcasting.page.patterns_as_iotas.advanced_parens.1",
"input": "num",
"patterns": {
"startdir": "SOUTH_WEST",
"signature": "eqqqe"
}
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.rawhook.hexcasting:close_all_parens",
"anchor": "hexcasting:close_all_parens",
"text": "hexcasting.page.patterns_as_iotas.advanced_parens.2",
"output": "num, [pattern]",
"patterns": {
"startdir": "SOUTH_EAST",
"signature": "qeeeq"
}
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.rawhook.hexcasting:undo",
Expand All @@ -60,6 +82,7 @@
},
{
"type": "patchouli:text",
"anchor": "further_notes",
"title": "hexcasting.page.patterns_as_iotas.further_notes.title",
"text": "hexcasting.page.patterns_as_iotas.further_notes.1"
},
Expand Down
Loading