From 24760b717c91695291f400943d6b72c9f5e5171a Mon Sep 17 00:00:00 2001 From: gamma-delta <29877714+gamma-delta@users.noreply.github.com> Date: Sat, 5 Nov 2022 19:34:01 +0100 Subject: [PATCH] working on new stack ops --- .../api/spell/iota/BooleanIota.java | 71 +++++++++++++++++++ .../common/casting/operators/stack/OpOver.kt | 13 ++++ .../casting/operators/stack/OpRotate.kt | 15 ++++ .../assets/hexcasting/lang/en_us.json | 26 ++++--- 4 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 Common/src/main/java/at/petrak/hexcasting/api/spell/iota/BooleanIota.java create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpOver.kt create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpRotate.kt diff --git a/Common/src/main/java/at/petrak/hexcasting/api/spell/iota/BooleanIota.java b/Common/src/main/java/at/petrak/hexcasting/api/spell/iota/BooleanIota.java new file mode 100644 index 00000000..71607ced --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/spell/iota/BooleanIota.java @@ -0,0 +1,71 @@ +package at.petrak.hexcasting.api.spell.iota; + +import at.petrak.hexcasting.api.utils.HexUtils; +import at.petrak.hexcasting.common.lib.HexIotaTypes; +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DoubleIota extends Iota { + public static final double TOLERANCE = 0.0001; + + public DoubleIota(double d) { + super(HexIotaTypes.DOUBLE, d); + } + + public double getDouble() { + return HexUtils.fixNAN((Double) this.payload); + } + + @Override + public boolean isTruthy() { + return this.getDouble() != 0.0; + } + + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof DoubleIota dd + && tolerates(this.getDouble(), dd.getDouble()); + } + + public static boolean tolerates(double a, double b) { + return Math.abs(a - b) < TOLERANCE; + } + + @Override + public @NotNull Tag serialize() { + return DoubleTag.valueOf(this.getDouble()); + } + + public static IotaType TYPE = new IotaType<>() { + @Nullable + @Override + public DoubleIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return DoubleIota.deserialize(tag); + } + + @Override + public Component display(Tag tag) { + return DoubleIota.display(DoubleIota.deserialize(tag).getDouble()); + } + + @Override + public int color() { + return 0xff_55ff55; + } + }; + + public static DoubleIota deserialize(Tag tag) throws IllegalArgumentException { + var dtag = HexUtils.downcast(tag, DoubleTag.TYPE); + return new DoubleIota(dtag.getAsDouble()); + } + + public static Component display(double d) { + return Component.literal(String.format("%.2f", d)).withStyle(ChatFormatting.GREEN); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpOver.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpOver.kt new file mode 100644 index 00000000..8305cfe0 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpOver.kt @@ -0,0 +1,13 @@ +package at.petrak.hexcasting.common.casting.operators.stack + +import at.petrak.hexcasting.api.spell.ConstManaAction +import at.petrak.hexcasting.api.spell.casting.CastingContext +import at.petrak.hexcasting.api.spell.iota.Iota + +// This is called "over" by uxn. Not +object OpYank : ConstManaAction { + override val argc: Int + get() = 2 + + override fun execute(args: List, ctx: CastingContext): List = listOf(args[0], args[0]) +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpRotate.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpRotate.kt new file mode 100644 index 00000000..d01ebe9e --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/operators/stack/OpRotate.kt @@ -0,0 +1,15 @@ +package at.petrak.hexcasting.common.casting.operators.stack + +import at.petrak.hexcasting.api.spell.ConstManaAction +import at.petrak.hexcasting.api.spell.casting.CastingContext +import at.petrak.hexcasting.api.spell.iota.Iota + +// Had never heard of this operation before i heard it from uxn, but turns out it's from forth +// see also http://www.forth.org/Ting/Forth-for-the-Complete-Idiot/Forth-79-Handy-Reference.pdf +// "fisherman's" is called "roll," apparently +object OpOver : ConstManaAction { + override val argc: Int + get() = 2 + + override fun execute(args: List, ctx: CastingContext): List = listOf(args[0], args[1], args[0]) +} diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.json b/Common/src/main/resources/assets/hexcasting/lang/en_us.json index 463010f1..0c2d24eb 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.json +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.json @@ -261,9 +261,9 @@ "hexcasting.spell.hexcasting:zone_entity/not_item": "Zone Dstl.: Non-Item", "hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Dstl.: Non-Player", "hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Dstl.: Non-Living", - "hexcasting.spell.hexcasting:const/null": "Nullary Reflection", "hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition", - "hexcasting.spell.hexcasting:duplicate_n": "Gemini's Gambit", + "hexcasting.spell.hexcasting:duplicate_n": "Gemini Gambit", + "hexcasting.spell.hexcasting:over": "Dioscuri Gambit", "hexcasting.spell.hexcasting:stack_len": "Flock's Reflection", "hexcasting.spell.hexcasting:swap": "Jester's Gambit", "hexcasting.spell.hexcasting:fisherman": "Fisherman's Gambit", @@ -364,6 +364,9 @@ "hexcasting.spell.hexcasting:akashic/read": "Akasha's Distillation", "hexcasting.spell.hexcasting:akashic/write": "Akasha's Gambit", "hexcasting.spell.hexcasting:read/entity": "Scribe's Purification", + "hexcasting.spell.hexcasting:const/null": "Nullary Reflection", + "hexcasting.spell.hexcasting:const/true": "True Reflection", + "hexcasting.spell.hexcasting:const/false": "False Reflection", "hexcasting.spell.hexcasting:const/vec/px": "Vector Reflection +X", "hexcasting.spell.hexcasting:const/vec/py": "Vector Reflection +Y", "hexcasting.spell.hexcasting:const/vec/pz": "Vector Reflection +Z", @@ -800,6 +803,7 @@ "hexcasting.page.sets.to_set": "Removes duplicate entries from a list.", "hexcasting.entry.consts": "Constants", + "hexcasting.page.consts.const/null": "Adds the $(l:casting/influences)$(thing)Null/$ influence to the top of the stack.", "hexcasting.page.consts.const/vec/x": "The left-hand counter-clockwise pattern adds [1, 0, 0] to the stack; the right-hand clockwise pattern adds [-1, 0, 0].", "hexcasting.page.consts.const/vec/y": "The left-hand counter-clockwise pattern adds [0, 1, 0] to the stack; the right-hand clockwise pattern adds [0, -1, 0].", "hexcasting.page.consts.const/vec/z": "The left-hand counter-clockwise pattern adds [0, 0, 1]; the right-hand clockwise pattern adds [0, 0, -1].", @@ -807,21 +811,21 @@ "hexcasting.page.consts.const/double/tau": "Adds τ, the radial representation of a complete circle, to the stack.", "hexcasting.page.consts.const/double/pi": "Adds π, the radial representation of half a circle, to the stack.", "hexcasting.page.consts.const/double/e": "Adds $(italic)e/$, the base of natural logarithms, to the stack.", - "hexcasting.page.consts.const/null": "Adds the $(l:casting/influences)$(thing)Null/$ influence to the top of the stack.", "hexcasting.entry.stackmanip": "Stack Manipulation", - "hexcasting.page.stackmanip.stack": "These patterns concern the $(l:casting/stack)$(thing)Stack/$ itself. Many of them pop different numbers of arguments and push different numbers of outputs depending on the inputs you give them. Such occurrences are written as \"many\".", + "hexcasting.page.stackmanip.pseudo-novice.title": "Novice's Gambit", + "hexcasting.page.stackmanip.pseudo-novice": "Removes the first iota from the stack.", + "hexcasting.page.stackmanip.duplicate": "Duplicates the top iota of the stack.", "hexcasting.page.stackmanip.swap": "Swaps the top two iotas of the stack.", + "hexcasting.page.stackmanip.rotate": "Yanks the iota third from the top of the stack to the top. [0, 1, 2] becomes [1, 2, 0].", + "hexcasting.page.stackmanip.over": "Duplicates the iota second from the top to the top. [0, 1] becomes [0, 1, 0].", + "hexcasting.page.stackmanip.duplicate_n": "Removes the number at the top of the stack, then copies the top iota of the stack that number of times. (A count of 2 results in two of the iota on the stack, not three.)", "hexcasting.page.stackmanip.fisherman": "Grabs the element in the stack indexed by the number and brings it to the top.", "hexcasting.page.stackmanip.stack_len": "Pushes the size of the stack as a number to the top of the stack. (For example, a stack of [0, 1] will become [0, 1, 2].)", - "hexcasting.page.stackmanip.last_n_list": "Remove $(italic)num/$ elements from the stack, then add them to a list at the top of the stack.", - "hexcasting.page.stackmanip.splat": "Remove the list at the top of the stack, then push its contents to the stack.", - "hexcasting.page.stackmanip.duplicate": "Duplicates the top iota of the stack.", - "hexcasting.page.stackmanip.duplicate_n": "Removes the number at the top of the stack, then copies the top iota of the stack that number of times. (A count of 2 results in two of the iota on the stack, not three.)", "hexcasting.page.stackmanip.mask.header": "Bookkeeper's Gambits", "hexcasting.page.stackmanip.mask.1": "An infinite family of actions that keep or remove elements at the top of the stack based on the sequence of dips and lines.", - "hexcasting.page.stackmanip.mask.2": "Assuming that I draw a Bookkeeper's Gambit pattern left-to-right, the number of iotas the action will require is determined by the horizontal distance covered by the pattern. From deepest in the stack to shallowest, a flat line will keep the iota, whereas a triangle dipping down will remove it.$(br2)If my stack contains $(italic)0, 1, 2/$ from deepest to shallowest, drawing the first pattern opposite will give me $(italic)1/$, the second will give me $(italic)0/$, and the third will give me $(italic)0, 2/$ (the 0 at the bottom is left untouched).", - "hexcasting.page.stackmanip.swizzle.1": "Rearranges the top elements of the stack based on the given numerical code, which is the index of the permutation wanted. Costs an amount of media that starts negligible and scales up as the numerical code does.", + "hexcasting.page.stackmanip.mask.2": "Assuming that I draw a Bookkeeper's Gambit pattern left-to-right, the number of iotas the action will require is determined by the horizontal distance covered by the pattern. From deepest in the stack to shallowest, a flat line will keep the iota, whereas a triangle dipping down will remove it.$(br2)If my stack contains $(italic)0, 1, 2/$ from deepest to shallowest, drawing the first pattern opposite will give me $(italic)1/$, the second will give me $(italic)0/$, and the third will give me $(italic)0, 2/$ (the 0 at the bottom is left untouched).$(br2)Given this, it seems $(l:hexcasting:pseudo-novice)$(action)Novice's Gambit/$ is a special case of this.", + "hexcasting.page.stackmanip.swizzle.1": "Rearranges the top elements of the stack based on the given numerical code, which is the index of the permutation wanted.", "hexcasting.page.stackmanip.swizzle.2": "Although I can't pretend to know the mathematics behind calculating this permutation code, I have managed to dig up an extensive chart of them, enumerating all permutations of up to six elements.$(br2)If I wish to do further study, the key word is \"Lehmer Code.\"", "hexcasting.page.stackmanip.swizzle.link": "Table of Codes", @@ -869,6 +873,8 @@ "hexcasting.page.lists.index_of": "Remove the iota at the top of the stack, then replace the list at the top with the first index of that iota within the list (starting from 0). Replaces the list with -1 if the iota doesn't exist in the list.", "hexcasting.page.lists.list_remove": "Remove the number at the top of the stack, then remove the nth element of the list at the top of the stack (where n is the number you removed).", "hexcasting.page.lists.modify_in_place": "Remove the top iota of the stack and the number at the top, then set the nth element of the list at the top of the stack to that iota (where n is the number you removed). Does nothing if the number is out of bounds.", + "hexcasting.page.lists.last_n_list": "Remove $(italic)num/$ elements from the stack, then add them to a list at the top of the stack.", + "hexcasting.page.lists.splat": "Remove the list at the top of the stack, then push its contents to the stack.", "hexcasting.page.lists.construct": "Remove the top iota, then add it as the first element to the list at the top of the stack.", "hexcasting.page.lists.deconstruct": "Remove the first iota from the list at the top of the stack, then push that iota to the stack.",