Magicard!

From Esolang
Jump to navigation Jump to search
Magicard
Paradigm(s) imperative
Designed by User:Quintopia
Appeared in 2013
Computational class Unknown computational class
Reference implementation Unimplemented
File extension(s) .mgc

Magicard! is a theme language created by User:Quintopia in 2013 in which programs consist of instructions for performing card tricks. It is rich with means of moving data from place to place, but there is no way of creating numeric literals singly. To get large literals, you must swamp yourself with smaller ones, then wade through the swamp to find the one you wanted. In addition, the only means of storing the result of an arithmetic operation is again, to wade through a swamp of literals looking for an answer that matches the one you wanted.

Data Organization

All data in Magicard is positive arbitrary-length integers. These integers are stored on cards which can be face-up or face-down, which are themselves initially stored in decks, which are deques. Every integer can be mapped to a deck, so there can be arbitrarily many decks. Each deck initially contains some number n of face-down cards, which contain the values 1 to n in ascending order from top to bottom. E.g., a freshly unboxed deck always has a 1 on top of it.

In addition to being in a deck, a card can be moved to one of four other places: table, spectator's hand, lap, or current packet. Cards can be retrieved from all of these places except lap, which is the clearing-house for all those unwanted extra literals.

There are several means of marking cards within the current deck or packet which may or may not remain in effect after certain operations are performed: side-jogs, in-jogs, up-jogs, pinky marks, and crimps. For instance, any command which squares the deck removes all jog marks.

Program

Magicard programs are imperative in nature, consisting of a series of instructions. Every instruction starts with a capital letter and ends with a period. Any string falling between valid instructions, which ends with a period or newline, but does not match an instruction, is a comment. Every program must begin with an Unbox instruction and end with TA-DA!

Some instructions take numbers and/or expressions as arguments. Numbers must be either entirely numeric, a unicode character enclosed in single quotes (with \ acting as an escape character in the usual way), or the token CRC. Expressions must be logical expression strings (evaluating to zero if false in the C fashion), not containing any spaces, which contain only numbers, the variables i,x, or d, and the operators ^, ||, &&, |, &, ~, ~~, -, +, *, **, /, %, =, <, >, !=, <=, and >=. (~~ means the unary Kronecker delta.) The variable x will evaluate to the value of the card for which the expression is evaluated if it is face-up, and an implementation-dependent value (such as NaN) which must cause any logical expression with which it is conjoined to evaluate to false if it is face-down. The variable i will evaluate to the position of the card for which the expression is evaluated within the deck or packet at the moment the command containing the expression was first invoked. The variable d will evaluate to the number of the current deck.

I/O

Magicard programs produce output in UTF-8, and assume all input is encoded the same way.

Instruction Set

First, we have the commands that select the current deck:

Command Behavior
Unbox deck [number] {of [num] cards}. Make the deck with the specified number the current deck If this is the first time this deck is unboxed, you must declare the number num of cards in it or receive a runtime error. If this is not the first time this deck is unboxed and a number of cards greater than the size of the deck is specified, emit an error, otherwise, take the top num cards of the deck as the current deck.
Rebox deck. Make the deck being used before the current deck was unboxed the current deck. This has no effect on any cards not currently in the deck. Emit a runtime error if the current deck is also the current packet.

These commands operate on the current deck. If the current deck does not contain at least the number of cards specified in the first column, that command will emit a runtime error.

Deck size req. Command Behavior
Ring in a cooler. Return the current deck to the condition it was in upon its first unboxing. Any cards missing from this deck that were in it originally will added to it from an unknown source. Any extra cards that were not in it will be sent to Lap.
Flip deck. Reverse the entire deck, and flip every card.
1 Reveal. Flip top card of deck.
2 Faro [in/out]. Permute the current deck in the fashion of a perfect Faro shuffle, leaving the original top card in the second/first position. This operation squares the deck. Will emit a runtime error if the current packet is not empty, because, dude, there's like one guy ever who can do a One-handed Faro.
num Shuffle {preserving [num] on [top/bottom]}. Shuffle the entire deck (except for the top/bottom num cards if specified). This operation squares the deck.
num Pinky-break [num]. Mark the numth card from the top with a pinky. This operation removes the side-jog mark if any.
num Riffle down [num]. Mark the numth card from the bottom with a pinky. This operation emits an error if the current packet is not empty, because it requires the other hand's thumb.
Multiple lift. Flip all cards above and including the pinky-breaked card, reversing their order.
Charlier cut. Move all cards above and including the current pinky-breaked card from the top to the bottom of the current deck. Removes pinky mark and side-jog.
Hot-shot cut. Move all cards below and including the current pinky-breaked card from the bottom to the top of the current deck and also move the card that was originally on the bottom of the deck to the top of the current packet. Removes pinky mark and side-jog.
Shadow pass. Move all cards from the second card up to and including the current pinky-breaked card to the bottom. Removes pinky mark and side-jog. This operation is two-handed (so the current packet must be empty).
num Count [num]. Move num cards from the top to the bottom of the deck, reversing their order. This two-handed operation requires an empty packet (use Biddle count if you need to count cards with a non-empty packet).
2 Houdini change. Swap the top two cards. This two-handed operation requires an empty packet.
2 Snap change. Swap the top two cards flipping the (new) second card. This two-handed operation requires an empty packet.
1 Wink change. Move the bottom card to the top, flipping it. This two-handed operation requires an empty packet.
1 Ego change. Move the top card to the bottom, flipping it. This two-handed operation requires an empty packet.
num [Side/in/up]-jog [num] from [top/bottom]. Mark the numth card from the top/bottom by side/in-jogging it. Any previously side/in-jogged cards will be unmarked. Note that these marks will be automatically removed by any operation which squares the deck. No card can have more than one sort of jog-mark.
Up-jog [expr]. Up-jog all cards which satisfy the given logical expression. All previously up-jogged cards remain up-jogged. This operation removes any side-jog marks, and the in-jogged card will lose that mark as well iff it is up-jogged.
1 Crimp. Mark the top card with a crimp. If the top card is already crimped, uncrimp it. If there is already a crimped card in the current deck, emit a runtime error. Crimps cannot be removed by any operation except for this one.
Pinky-break at [side-/in-/first up-/last up-]jog. Create a pinky mark below the side-jogged/in-jogged/first (nearest the top) up-jogged/last (nearest the bottom) up-jogged card. If no such card exists, emit a runtime error.
Pinky-break at crimp. Create a pinky mark below the crimped card. If no such card exists, emit a runtime error.
Side-jog card above pinky-break. Exactly what it says. If no pinky mark exists, emit a runtime error.
All-around square-up to [in-/up-]jog Changes the side-jog mark into an in-jog mark (removing the current in-jog mark) or an up-jog mark. Emits runtime error if there is no side-jog mark. This two-handed operation requires an empty packet.
Square deck. Remove marks from all up/side/in-jogged cards.
Roadrunner cull [expr]. Move all cards satisfying the given expression to the bottom maintaining their order relative to one another. This operation removes the side-jog mark if any, and any marks on the cards which are moved. This two-handed operation requires an empty packet.
Table spread. Print all face-up cards (the corresponding Unicode codepoints) from bottom to top, except for the side-jogged card if any. This operation squares the deck.
Flip table spread. Print all face-down cards (the actual numbers, one per line) from top to bottom, except for the card above the side-jogged card, if any. Deck will be reversed with all cards flipped afterward. This operation squares the deck.
Have a card selected [face-up/face-down]. Get user input (in the form of a character if face-up or a newline-terminated string parse-able as a number if face-down). Move all cards above the card with that value to the bottom and ensure that it is in the proper orientation. Raise a runtime error if that card is not in the current deck. This operation removes the side-jog mark as well as any mark on the input card. This two-handed operation requires an empty packet.
1 Name. If there is no face-up card on top of the current deck, flip the top card. Declare the face-up card on top of the deck the Current Remembered Card (CRC). The token "CRC" can be used wherever a command would otherwise take a number to use the number on this card instead. Doing so will cause a runtime error if no card has been Named.
Find. Move all cards above the first occurrence of the CRC to the bottom of the current deck. If the CRC is not in the current deck, emit a runtime error. This operation removes the side-jog mark, if any. This two-handed operation requires an empty packet.
Spread cull. Move the CRC to the bottom of the current deck iff it is face-up. If the CRC is not face-up in the current deck, emit a runtime error. This operation removes the side-jog mark, if any. This two-handed operation requires an empty packet.
0(plain/bottom) or 1(second/greek/center) {[Second/Bottom/Greek/Center]} Deal [num] card[s] [instructions]. Deal num cards in the prescribed fashion, following the instructions for each card. Plain and second dealing pop cards from the top down, and bottom/greek/center dealing pop cards from the bottom up. Second dealing pops from the second-from-the-top position. Bottom pops from the bottom. Greek pops from the second from the bottom. Center pops from directly above the side-jogged card, or from a random position at least min(num,size-of-deck) from the top if there isn't one. If there are less than num cards to be dealt, pop as many as possible and stop. This operation removes any marks on the dealt cards, and turns the side-jog mark, if any, into a pinky-break. If a destination is not specified, dealt cards will be returned to the top of the deck in reverse order.

Legal instructions for a deal:

  • {and} to table {if [expr]} = leave the dealt card on top of a pile on the table (if the expression is true)
  • {and} to spectator {if [expr]} = leave the dealt card on top of a pile in the spectator's hand (if the expression is true)
  • {and} to lap {if [expr]} = discard card to lap (if the expression is true)
  • {and} to top of deck if [expr] = deal to the top of the deck (like the default behavior, but can be used when non-default dealing location is used.
  • Green-style {if [expr]} = move card to the top of the current packet (if the expression is true)
  • flipping each one {if [expr]} = flip the dealt card (if the expression is true)
  • dealing every [num]th card [from the top/from the bottom/from the center/seconds/Greek] = deal the numth card from the specified position instead
  • with a flourish {if [expr]} = print the card's character (if face-up) or number (if face-down) value (if the expression is true)
num Take {[num] cards from} pile from [table/spectator's hand] to [top/bottom] of deck. Move the top num cards (or all cards) from the specified place to the top/bottom of the current deck.

The following operations move cards between the current deck and the current packet. They will cause a runtime error if the deck (if cards are leaving the deck) or the packet (if cards are leaving the packet) contains fewer cards than the value in the first column. Furthermore, unless otherwise stated, up-jogged cards which move between the deck and the packet will remain up-jogged, while all pinky, in-jog and side-jog marks will be removed. Moving a crimped card to a deck or packet which already contains a crimped card will cause a runtime error.

Deck size req. Command Behavior
Set down deck. Make the current packet the current deck in addition to being the current packet. If the current deck is already the current packet, emit a runtime error.
Pick up deck. If a deck has previously been set down, make it the current deck. Otherwise, emit a runtime error.
num Put {[num] cards from [top/bottom] of} packet {on top/on bottom/in the middle} of deck. Move the top/bottom num cards (or all cards) from the current packet to the top/bottom of the current deck or to just above the current side-jogged card. (If no card is side-jogged, "in the middle" will go to a random position within 6 cards of the middle of the deck.)
[Back-/Side-]steal. If a card is in-jogged/side-jogged, move it to the bottom of the current packet. Otherwise, emit a runtime error.
Strip out. Take all cards which are up-jogged and move them to the bottom of the current packet, removing their up-jog marks.
num Take packet of [num] from [top/bottom]. Make the top/bottom num cards of the deck the current packet (without changing their order). If there is already a current packet, append these cards to its bottom.
1 KM Move. Move the bottom card of the current packet to the top of the current deck, flipping it.
Top change. Exchange the entire packet for all cards in the deck above a pinky mark, leaving the former packet on top of the deck.
Bottop change. Exchange the entire packet for all cards in the deck below a pinky mark, leaving the former packet on the bottom.
n Subtle poker move. If the current packet contains n cards, move all but the bottom n cards of the deck to the bottom of the packet.
2 Vernon depth illusion. Insert the packet between the top and second cards of the deck. This operation removes all jog marks from the inserted cards.
2 Marlo tilt. Golfy synonym for Vernon depth illusion.
num Biddle count [num] {stealing when [expr]}. Move num cards from top of deck to top of packet, reversing their order. If the expression is true, the card is placed on the bottom of the deck instead.

The following instructions operate on the current packet only when it is also the current deck. In other words, if they are issued before a Set down deck., there will be a runtime error. In addition, they will emit a runtime error if the size of the packet is less than the number in parens. All of these operations remove ALL jog marks and pinky marks.

Deck size req. Command Behavior
2 Elmsley count. Move the bottom card of the packet to second from the top of the packet.
2 Jordan count. Move the second card of the packet to the bottom of the packet (the inverse operation of Elmsley Count).
2 Gemini count. Move the top card of the packet to second from the bottom of the packet.
1 Flustration count. Reverse the packet.
4 Ascanio fan. For the top card and the three on the bottom (from top to bottom), print their Unicode values in sequence if they are face-down.

The following instructions work on the packet even when it is not the current deck. They also emit errors when their packet size requirement isn't met.

Packet size req. Command Behavior
Lap. Move entire packet to lap.
num Pinky-break packet [num] Same as for the deck (but with the other hand).
Charlier cut packet. Same as for the deck (but with the other hand).
num Shuffle packet {preserving [num] on [top/bottom]}. Same as for the deck (but with the other hand).
Flip packet. Same as for the deck.
{Bottom} Deal [num] from packet [instructions]. The one-handed deal supports only plain top-dealing and bottom-dealing. The only instructions permitted are "to table", "to spectator", "to lap", "to top of deck {if [expr]}", and "flipping each one". The default dealing method is "to top of deck". It is impossible to deal from the packet back onto the packet without making it the current deck first.
Table spread packet. Same as for the deck.
Flip table spread packet. Same as for the deck.
Square up packet. Same as for the deck.
Pinky-break packet at [side-/in-/first up-/last up-]jog. Same as for deck.
Pinky-break packet at crimp. Same as for deck.
Side-jog card above packet pinky-break. Yep.
Multiple lift packet. Yeppers.

The following instructions are the only means of flow control.

Command Behavior
Do last [num] step[s] again if [expr]. Repeat the preceding num commands if the expression is true.
Repeat on next [num] decks. Repeat all commands beginning at the last Unbox command num times, incrementing the deck number by 1 each time. If no deck with the deck number exists, create one with the same number of cards as the current deck had when this command was first executed.
Perform [name] starting with deck [num]. Load the file "name.mgc" and interpret and execute its contents as Magicard! code, adding num to the first argument of every Unbox command.
TA-DA! Halt. Due to the inability to skip over any instruction in this language, it will always and only be the last instruction (so any instructions after it can be considered comments).

Computational Class

MAYBE Turing-complete. Maybe just total. WHO KNOWS?

Examples

Cat:

Unbox deck 0 of 4294967296 cards.
Have a card selected face-up.
Name.
Deal 1 card with a flourish.
Ring in a cooler.
Do last 4 steps again if CNC!=10.
TA-DA!

Long Hello World:

Unbox deck 0 of 127 cards.
Take packet of 127 from top.
Repeat on next 11 decks.
Put packet on top of deck.
Pinky-break 'H'.
Charlier cut.
Riffle down 'H'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'e'.
Charlier cut.
Riffle down 'e'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'l'.
Charlier cut.
Riffle down 'l'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'l'.
Charlier cut.
Riffle down 'l'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'o'.
Charlier cut.
Riffle down 'o'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break ' '.
Charlier cut.
Riffle down ' '.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'W'.
Charlier cut.
Riffle down 'W'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'o'.
Charlier cut.
Riffle down 'o'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'r'.
Charlier cut.
Riffle down 'r'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'l'.
Charlier cut.
Riffle down 'l'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 'd'.
Charlier cut.
Riffle down 'd'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break '!'.
Charlier cut.
Riffle down '!'.
Hot-shot cut.
Pinky break 126.
Charlier cut.
Pinky-break 10.
Charlier cut.
Riffle down 10.
Hot-shot cut.
Set down deck.
Bottom Deal 12 cards flipping each one with a flourish.
TA-DA!

Hello World without using packet:

Unbox deck 0 of 127 cards.
Crimp.
Flip deck.
Riffle down 'H'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'e'
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'l'
Charlier cut.
Deal 1 card with a flourish.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'o'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down ' '.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'W'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'o'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'r'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'l'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down 'd'.
Charlier cut.
Deal 1 card with a flourish.
Pinky-break at crimp.
Charlier cut.
Riffle down '!'.
Charlier cut.
Deal 1 card with a flourish.
TA-DA!

Shorter Hello World:

Unbox deck 0 of 127 cards.
Take packet of 127 from top.
Repeat on next 5 decks.
Put packet on top of deck.
Biddle count 127 stealing when i='H'||i='e'||i='l'.
Biddle count 127 stealing when i='l'||i='o'.
Biddle count 127 stealing when i=' '||i='W'||i='o'||i='r'
Biddle count 127 stealing when i='l'.
Biddle count 127 stealing when i='d'.
Biddle count 127 stealing when i='!'.
Deal 12 cards flipping each one with a flourish.
TA-DA!

Faster Hello World:

Unbox deck 0 of 122 cards.
Flip deck.
Upjog x='H'||x='e'||x='l'||x='o'||x=' '||x='W'||x='r'||x='d'||x='!'||x='z'.
Strip out.
Set down deck.                                                              
Flustration count.                                                          # !HWdelorz
Roadrunner cull x='H'||x='e'||x='l'||x='o'||x='z'.                          # !WdrHeloz
Roadrunner cull x=' '||x='W'||x='r'||x='z'.                                 #!dHelo Wrz
Roadrunner cull x='!'||x='d'||x='z'                                         #Helo Wr!dz
Deal 2 cards to spectator with a flourish.                                  #lo Wr!dz
Deal 1 card with a flourish.                                                
Deal 1 card with a flourish.
Gemini count.                                                               #o Wr!dlz
Deal 1 card with a flourish.
Gemini Count.                                                               # Wr!dloz
Deal 2 cards to spectator with a flourish.                                  #r!dloz
Flustration count.                                                          #zold!r
Deal 1 card to spectator.                                                   #old!r
Elmsley count.                                                              #orld!
Deal 5 cards with a flourish.
TA-DA!

LSB Radix Sort (also known as the Chinese Shuffle):

#shuffle the capital letters, then sort them, and print them in order again.
Unbox deck 0 of 127 cards.
Flip deck.
Biddle count 127 stealing when x>='A'&&x<='Z'.
Lap.
Shuffle.
Take packet of 26 from top.
Unbox deck 1 of 0 cards.
Put packet on top of deck.
Roadrunner cull x%2**d>2**(d-1).
Take packet of 26 from top.
Repeat on next 4 decks.
Put packet on top of deck.
Deal 26 cards with a flourish.
TA-DA!