Difference between revisions of "User:Pseudosphere"

From The Wiki Camp 2
Jump to navigationJump to search
m
m (Undo revision 119957 by Pseudosphere (talk))
Tag: Undo
Line 531: Line 531:
 
def stategen(state):
 
def stategen(state):
 
     return (*(n < state[0] for n in range(nurpos)), state[0] == 0 and state[1] == 3, state[0] == 0 and state[1] != 3)
 
     return (*(n < state[0] for n in range(nurpos)), state[0] == 0 and state[1] == 3, state[0] == 0 and state[1] != 3)
stateMachine = mwcollapse.genStateMachine((0, 1), transition, stategen, (nurpos, nurpos & 3))
+
stateMachine = mwcollapse.genStateMachine((0, 1), transition, stategen, (nurpos, 3))
 
elementContainer = mwcollapse.ElementContainer('<p class="nurpons">', *(mwcollapse.Collapsible("span", n, "[[File:Nerpawhite.png|64px|link=]]") for n in range(nurpos)), '</p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 1, "Remove one", attributes={"class": "nimbutton"}), '<span class="nobutton">Remove one</span></p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 0, "End turn", attributes={"class": "nimbutton"}), '<span class="nobutton">End turn</span></p>', mwcollapse.Collapsible("p", nurpos, "YOU LOSE", attributes={"class": "bigtexty"}), mwcollapse.Collapsible("p", nurpos + 1, "YOU [[Win|WIN]]", attributes={"class": "bigtexty"}))
 
elementContainer = mwcollapse.ElementContainer('<p class="nurpons">', *(mwcollapse.Collapsible("span", n, "[[File:Nerpawhite.png|64px|link=]]") for n in range(nurpos)), '</p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 1, "Remove one", attributes={"class": "nimbutton"}), '<span class="nobutton">Remove one</span></p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 0, "End turn", attributes={"class": "nimbutton"}), '<span class="nobutton">End turn</span></p>', mwcollapse.Collapsible("p", nurpos, "YOU LOSE", attributes={"class": "bigtexty"}), mwcollapse.Collapsible("p", nurpos + 1, "YOU [[Win|WIN]]", attributes={"class": "bigtexty"}))
 
elementContainer.compile("nim", stateMachine)
 
elementContainer.compile("nim", stateMachine)

Revision as of 06:37, 11 April 2024

Notepad24.png

Pages I made which are actually good

Scripts I made for pages

Licensing

  1. Anyone can use or modify these scripts for whatever, except for evil doings.
  2. Anyone can distribute any of these scripts or derivative works thereof, as long as they specify which of my scripts was used or modified, and link back to their source.
  3. These scripts can also be relicensed under any GPL-compatible license, as long as line 2 is still obeyed.

THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL I BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Tesseract CSS generator

#!/bin/python3
from math import tau, cos, sin

#Transform of v-w plane for w=1
# v       w
#|A       -B*100|
#|nC/100 -nD+n+1|

def S(x):
    y = int(x)
    if x == y:
        return str(y)
    r = str(x)
    if r.find("e") != -1:
        return "0"
    return r

#def genTransform(theta, n):
#    c = cos(theta)
#    s = sin(theta)
#    return ("transform:matrix3d(", S(c), ",0,0,", S(n * s * 0.01), ",0,1,0,0,0,0,1,0,", S(s * 100), ",0,0,", S(n - n * c + 1), ");")

def genTransform2(theta, n, A, B, C, D):
    c = cos(theta)
    s = sin(theta)
    return ("transform:matrix3d(", S(c), ",0,0,", S(n * s * 0.01), ",0,", A, ",", C, ",0,0,", B, ",", D, ",0,", S(s * 100), ",0,0,", S(n - n * c + 1), ");")

#for n in range(64):
#    k = n / 64
#    print(k * 100, "%{", sep="")
#    print(*genTransform(k * tau, 0.5), "}", sep="")

def genTransforms(name, offset, A, B, C, D):
    print("@keyframes ", name, "{100%,", sep="", end="")
    for n in range(256):
        k = n / 256
        print(S(k * 100), "%{", *genTransform2((k + offset) * tau, 0.5, A, B, C, D), "}", sep="", end="")
    print("\n}", end="")

genTransforms("cell-front", 0, "1", "0", "0", "1")
genTransforms("cell-right", 0.25, "0", "1", "-1", "0")
genTransforms("cell-back", 0.5, "-1", "0", "0", "-1")
genTransforms("cell-left", 0.75, "0", "-1", "1", "0")

Brainfuck Rot13 Demo

----------[
[++++++++++<<,.----------] get str
>>[>>]<< go to start
[
---------------------------------------------------- to position plus 13
>++++++++++++++++++++++++++< d = 26
[>->+<[>]>[<+>-]<<[<]>-] modulo
>[-] clear junk
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-] print character & clear cell
<<<< next char
]
++++++++++.---------- newline
----------]

Φιnary animation generator

#!/bin/python3

s="""0000000.000000
0000001.000000
0000010.010000
0000100.010000
0000101.010000
0001000.100100
0001010.000100
0010000.000100
0010001.000100
0010010.010100
0010100.010100
0010101.010100
0100000.101001
0100001.101001
0100100.001001
0100101.001001
0101000.100001
0101010.000001
1000000.000001
1000001.000001
1000010.010001
1000100.010001
1000101.010001
1001000.100101
1001010.000101
1010000.000101
1010001.000101
1010010.010101
1010100.010101
1010101.010101""".replace(".", "").split("\n")

for n in range(len(s[0])):
    z.clear()
    o.clear()
    print("@keyframes flippyphi", n, " {", sep="")
    for k in range(len(s)):
        if s[k][n] == "1":
            o.append(k * 100 / len(s))
        else:
            z.append(k * 100 / len(s))
    print(*z, sep="%,", end="%,100% {height: 4px;}\n")
    print(*o, sep="%,", end="% {height: 16px;}\n}\n")

Nim generator

#!/bin/python3

turns = 8

firstturn = turns - 1

print(end="<p class=\"nurpons\">")
for n in range(turns):
    k = n * 4
    print("<span class=\"mw-collapsible\" id=\"mw-customcollapsible-nerpyblock", n, "\">[[File:Nerpawhite.png|64px|link=]]<span class=\"mw-collapsible\" id=\"mw-customcollapsible-nerpy", k + 1, "\">[[File:Nerpawhite.png|64px|link=]]</span><span class=\"mw-collapsible\" id=\"mw-customcollapsible-nerpy", k + 2, "\">[[File:Nerpawhite.png|64px|link=]]</span><span class=\"mw-collapsible\" id=\"mw-customcollapsible-nerpy", k + 3, end="\">[[File:Nerpawhite.png|64px|link=]]</span></span>", sep="")
print("</p>")

print(end="<p class=\"nimbuttons\">")
for n in range(turns):
    k = n * 4
    print(end="<span class=\"mw-collapsible")
    if n != firstturn:
        print(end=" mw-collapsed")
    print("\" id=\"mw-customcollapsible-turn", n, "\"><span class=\"mw-collapsible mw-collapsed nimbutton mw-customtoggle-nim", k + 1, " mw-customtoggle-nerpy", k + 1, "\" id=\"mw-customcollapsible-nim", k + 1, "\">Remove one</span><span class=\"mw-collapsible mw-collapsed nimbutton mw-customtoggle-nim", k + 1, " mw-customtoggle-nim", k + 2, " mw-customtoggle-nerpy", k + 2, "\" id=\"mw-customcollapsible-nim", k + 2, "\">Remove one</span><span class=\"mw-collapsible nimbutton mw-customtoggle-nim", k + 2, " mw-customtoggle-nim", k + 3, " mw-customtoggle-nerpy", k + 3, " mw-customtoggle-endturn", n, "\" id=\"mw-customcollapsible-nim", k + 3, end="\">Remove one</span><span class=\"nobutton\">Remove one</span></span>", sep="")
print("<span class=\"nobutton\">Remove one</span></p>")

print(end="<p class=\"nimbuttons\">")
for n in range(turns):
    print("<span class=\"mw-collapsible mw-collapsed nimbutton mw-customtoggle-endturn", n, end="", sep="")
    if n != 0:
        print(" mw-customtoggle-turn", n - 1, end="", sep="")
    else:
        print(end=" mw-customtoggle-loser")
    print(" mw-customtoggle-turn", n, " mw-customtoggle-nerpyblock", n, "\" id=\"mw-customcollapsible-endturn", n, end="\">End turn</span>", sep="")
print("<span class=\"nobutton\">End turn</span></p>\n<p style=\"font-size: 500%; font-weight: bold; text-align: center;\" class=\"mw-collapsible mw-collapsed\" id=\"mw-customcollapsible-loser\">YOU LOSE</p>")

mwcollapse.py

A python module for converting finite-state machines into mw-collapsible spaghetti. Works best with tree-like systems; is very inefficient for highly "symmetric" FSMs, since the output size is proportional to the number of state transitions.

class StateNode:
    __slots__ = "state", "transitions"
    def __init__(self, state, transitions=None):
        self.state = tuple(state)
        self.transitions = {} if transitions == None else transitions
    def __call__(self, var):
        return self.state[var]
    def __len__(self):
        return len(self.transitions)
    def __length_hint__(self):
        return len(self.transitions)
    def __getitem__(self, key):
        return self.transitions[key]
    def __setitem__(self, key, value):
        self.transitions[key] = value
    def __delitem__(self, key):
        del self.transitions[key]
    def __iter__(self):
        return iter(self.transitions)
    def __reversed__(self):
        return reversed(self.transitions)
    def __contains__(self, item):
        return item in self.transitions
class StateMachine:
    __slots__ = "states"
    def __init__(self, *states):
        self.states = states
    def __repr__(self):
        return f"<StateMachine object of {len(self.states)} states>"
    def __bool__(self):
        return bool(self.states)
    def __len__(self):
        return len(self.states)
    def __length_hint__(self):
        return len(self.states)
    def __getitem__(self, key):
        return self.states[key]
    def __iter__(self):
        return iter(self.states)
    def __reversed__(self):
        return reversed(self.states)
    def __contains__(self, item):
        return item in self.states
    def index(self, value):
        return self.states.index(value)

class ElementContainer:
    """An Element-like sequence of Element-like objects."""
    __slots__ = "_children", "_parent"
    def __init__(self, *children):
        self._children = children
        self._parent = None
        for c in children:
            if isinstance(c, ElementContainer):
                c._parent = self
    def __str__(self):
        return "".join(str(c) for c in self._children)
    def compile(self, identifier, statemachine):
        for child in self._children:
            if isinstance(child, ElementContainer):
                child.compile(identifier, statemachine)
    def visible(self, state):
        return self._parent == None or self._parent.visible(state)
class Element(ElementContainer):
    """An HTML element"""
    __slots__ = "_attributes", "_children", "name", "_parent"
    @staticmethod
    def _gentag(l, name, attributes, children):
        l.append("<")
        l.append(name)
        for k in attributes:
            l.append(" ")
            l.append(k)
            l.append("=\"")
            l.append(attributes[k].replace("&", "&amp;").replace('"', "&quot;"))
            l.append("\"")
        l.append(">")
        l.extend(str(c) for c in children)
        l.append("</")
        l.append(name)
        l.append(">")
    def __init__(self, name, *children, attributes=None):
        super().__init__(*children)
        self._attributes = {} if attributes == None else attributes.copy()
        self.name = name
    def __str__(self):
        l = []
        self._gentag(l, self.name, self._attributes, self._children)
        return "".join(l)

class Toggleable(Element):
    """An mw-collapsible HTML element; might still be visible when collapsed.
var = index into a boolean tuple of collapsible states;
should not be shared with other elements."""
    __slots__ = "var"
    def __init__(self, name, var, *children, attributes=None):
        super().__init__(name, *children, attributes=attributes)
        self.var = var
    def compile(self, identifier, statemachine):
        self._attributes["id"] = f"mw-customcollapsible-{identifier}-{self.var}"
        self._attributes["class"] = self._attributes["class"] + (" mw-collapsible" if statemachine[0](self.var) else " mw-collapsible mw-collapsed") if "class" in self._attributes else ("mw-collapsible" if statemachine[0](self.var) else "mw-collapsible mw-collapsed")
        super().compile(identifier, statemachine)
class Collapsible(Toggleable):
    """An mw-collapsible HTML element; should always be hidden while collapsed.
var = index into a boolean tuple of collapsible states;
should not be shared with other elements."""
    def visible(self, state):
        return state(self._var) and super().visible(state)

class Trigger(Element):
    """A sequence of mw-customtoggle HTML elements."""
    __slots__ = "event", "_identifier", "_toggles"
    def __init__(self, name, event, content="", attributes=None):
        super().__init__(name, content, attributes=attributes)
        self.event = event
    def __str__(self):
        hasclass = "class" in self._attributes
        l = []
        for i, toggle in enumerate(self._toggles):
            if toggle != None:
                attributes = self._attributes.copy()
                attributes["id"] = f"mw-customcollapsible-{self._identifier}-t{i}-{self.event}"
                attributes["class"] = " ".join((attributes["class"], *toggle) if hasclass else toggle)
                self._gentag(l, self.name, attributes, self._children)
        return "".join(l)
    def compile(self, identifier, statemachine):
        self._identifier = identifier
        self._toggles = tuple(self._gentoggle(statemachine, state, i) for i, state in enumerate(statemachine))
    def _gentoggle(self, states, state, index):
        if self.event in state and self.visible(state):
            s = {"mw-collapsible"}
            if index != 0:
                s.add("mw-collapsed")
            tstate = state[self.event]
            if state != tstate:
                s.update(f"mw-customtoggle-{self._identifier}-{n}" for n in range(len(state.state)) if state(n) != tstate(n))
                s.update(f"mw-customtoggle-{self._identifier}-t{index}-{event}" for event in state)
                s.update(f"mw-customtoggle-{self._identifier}-t{states.index(tstate)}-{event}" for event in tstate)
            else:
                s.add("mw-redundanttoggle")
            return s
        return None

def _genNode(transitions, d, l, transition, stategen, s):
    if s not in d:
        node = StateNode(stategen(s))
        d[s] = node
        l.append(node)
        for t in transitions:
            newstate = transition(s, t)
            if None != newstate:
                node[t] = _genNode(transitions, d, l, transition, stategen, newstate)
        return node
    return d[s]

def genStateMachine(transitions, transition, stategen, initial):
    """Generates a state machine from a transition function.
transitions is an iterable of transition names (the inputs to the state machine).
transition is a function accepting a state (which can be any hashable object) and a transition name;
it returns a new state deterministically and without side effects, or None if the transition name is not applicable for this state.
stategen converts a state to an iterable of boolean values representing the states of collapsibles.
initial is the initial state of the machine."""
    l = []
    _genNode(transitions, {}, l, transition, stategen, initial)
    return StateMachine(*l)

def collapseTrigger(name, event, var, content="", attributes=None):
    """Convenience function to generate a Trigger and Collapsible which can substitute each other."""
    return ElementContainer(Trigger(name, event, content, attributes=attributes), Collapsible(name, var, content, attributes=attributes))

def example():
    """An example function generating a simple counter."""
    
    # <!--HTML pseudocode for this example-->
    #
    # <initial>
    #     let $COUNTER = 0;
    # </initial>
    #
    # <transition id="increment">
    #     if $COUNTER != 99 then increment $COUNTER;
    # </transition>
    # <transition id="decrement">
    #     if $COUNTER != 0 then decrement $COUNTER;
    # </transition>
    #
    # <stategen>
    #     display collapsibles with id == ((tens digit of $COUNTER) + 10) or id == (ones digit of $COUNTER);
    # </stategen>
    #
    # <span collapsible-id="10"></span><span collapsible-id="11">1</span><!--...--><span collapsible-id="19">9</span><span collapsible-id="0">0</span><!--...--><span collapsible-id="9">9</span><br/>
    # <span trigger-id="increment" style="background-color:#000;border:1px solid;color:#0F0;">+</span><br/>
    # <span trigger-id="decrement" style="background-color:#000;border:1px solid;color:red;">-</span>
    
    def transition(state, transition):
        if transition == "increment":
            return None if state == 99 else state + 1
        return None if state == 0 else state - 1
    def stategen(state):
        l = [n == state % 10 for n in range(10)]
        l.extend(n == state // 10 for n in range(10))
        return tuple(l)
    stateMachine = genStateMachine(("increment", "decrement"), transition, stategen, 0)
    elements = [Collapsible("span", 10, "")]
    elements.extend(Collapsible("span", n + 10, str(n)) for n in range(1, 10))
    elements.extend(Collapsible("span", n, str(n)) for n in range(10))
    elements.append("<br/>\n")
    elements.append(Trigger("span", "increment", "+", attributes={"style": "background-color:#000;border:1px solid;color:#0F0;"}))
    elements.append("<br/>\n")
    elements.append(Trigger("span", "decrement", "-", attributes={"style": "background-color:#000;border:1px solid;color:red;"}))
    elementContainer = ElementContainer(*elements)
    elementContainer.compile("counter", stateMachine)
    print(elementContainer)

Calculator 2.0 generator

#!/bin/python3
import mwcollapse

def transition(state, transition):
    if transition == "AC" and state[0] != -1:
        return (-1, None, -1)
    elif transition == "equ":
        if state[2] != -1:
            if state[1] == "add":
                return ((state[0] + state[2]) % 10, None, -1)
            if state[1] == "sub":
                return ((state[0] - state[2]) % 10, None, -1)
            if state[1] == "mul":
                return (state[0] * state[2] % 10, None, -1)
            return (state[0] // state[2] % 10, None, -1)
    elif transition in "0123456789":
        if state[0] == -1:
            return (int(transition), None, -1)
        if state[1] != None and (state[1] != "div" or transition != "0") and state[2] == -1:
            return (state[0], state[1], int(transition))
    elif transition in ("add", "sub", "mul", "div") and state[1] == None and state[2] == -1:
        return (0 if state[0] == -1 else state[0], transition, -1)
    return None
def stategen(state):
    l = [n == state[0] for n in range(-1, 10)]
    l.extend(s == state[1] for s in (None, "add", "sub", "mul", "div"))
    l.extend(n == state[2] for n in range(-1, 10))
    digits = state[0] != -1 and (state[1] == None or state[2] != -1)
    ops = state[1] != None
    l.extend(digits for n in range(10))
    l.extend(ops for n in range(4))
    l.append(state[0] == -1)
    l.append(state[2] == -1)
    return tuple(l)
table = mwcollapse.Element("table", '<tr><th colspan="4"><span class="display">', *(mwcollapse.Collapsible("span", i, v) for i, v in enumerate(" 0123456789 +-*/ 0123456789")), "</span></th></tr><tr>", *(mwcollapse.Element("td", mwcollapse.collapseTrigger("span", str(n), n + 27, str(n))) for n in range(7, 10)), "<td>", mwcollapse.collapseTrigger("span", "add", 37, "+", attributes={"class": "op"}), "</td></tr><tr>", *(mwcollapse.Element("td", mwcollapse.collapseTrigger("span", str(n), n + 27, str(n))) for n in range(4, 7)), "<td>", mwcollapse.collapseTrigger("span", "sub", 38, "-", attributes={"class": "op"}), "</td></tr><tr>", *(mwcollapse.Element("td", mwcollapse.collapseTrigger("span", str(n), n + 27, str(n))) for n in range(1, 4)), "<td>", mwcollapse.collapseTrigger("span", "mul", 39, "×", attributes={"class": "op"}), "</td></tr><tr><td>", mwcollapse.collapseTrigger("span", "AC", 41, "AC", attributes={"class": "AC"}), "</td><td>", mwcollapse.collapseTrigger("span", "0", 27, "0"), "</td><td>", mwcollapse.collapseTrigger("span", "equ", 42, "=", attributes={"class": "equ"}), "</td><td>", mwcollapse.collapseTrigger("span", "div", 40, "÷", attributes={"class": "op"}), "</td></tr>", attributes={"class": "calculator"})
table.compile("calc", mwcollapse.genStateMachine(("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "add", "sub", "mul", "div", "equ", "AC"), transition, stategen, (-1, None, -1)))
print(table)

Notakto generator

#!/bin/python3
import mwcollapse

boot = (49, 82, 148, 280, 49, 82, 148, 280)

class State:
    __slots__ = "state", "bools", "transition"
    def __init__(self, state, transition=None):
        self.state = state
        self.bools = tuple((state & 1 << n) != 0 for n in range(9) if n != 4)
        self.transition = transition
    def __eq__(self, other):
        return self.state == other.state
    def __hash__(self):
        return self.state
    def __len__(self):
        return self.bools.count(True)
    def __getitem__(self, key):
        return True if key == None or key == ... else self.bools[key]
    def gameover(self):
        return (self.bools[0] and self.bools[1] and self.bools[2]) or (self.bools[0] and self.bools[3] and self.bools[5]) or (self.bools[0] and self.bools[7]) or (self.bools[1] and self.bools[6]) or (self.bools[2] and self.bools[5]) or (self.bools[2] and self.bools[4] and self.bools[7]) or (self.bools[3] and self.bools[4]) or (self.bools[5] and self.bools[6] and self.bools[7])

varToPos = lambda n: n if n < 4 else n + 1
posToVar = lambda n: n if n < 4 else n - 1

def transition(state, transition):
    if not state[0].gameover():
        if not state[1]:
            if transition == None:
                if len(state[0]) == 1:
                    return State(boot[state[0].transition]), True, False
                for n in range(9):
                    if not state[0][n]:
                        s = State(state[0].state | 1 << varToPos(n))
                        if not s.gameover():
                            return s, True, False
        elif not state[0][transition]:
            s = State(state[0].state | 1 << varToPos(transition), transition)
            return s, False, s.gameover()
    elif transition == ...:
        return (State(0b000010000), True, False)
    return None
e = mwcollapse.ElementContainer(
    '<p style="text-align: center;">',
    mwcollapse.Trigger("span", None, "End turn", attributes={"class": "nimbutton"}),
    mwcollapse.Collapsible("span", 8, "End turn", attributes={"class": "nobutton"}),
    mwcollapse.Trigger("span", ..., "Try again", attributes={"class": "nimbutton"}),
    '</p><table class="tictactoe">',
    *(mwcollapse.Element("tr",
        *(mwcollapse.Element("td",
            '<span class="cell">X</span>' if k == 4 else mwcollapse.ElementContainer(
                mwcollapse.Trigger("span", posToVar(k), attributes={"class": "cell"}),
                mwcollapse.Collapsible("span", posToVar(k), "X", attributes={"class": "cell"})
            ),
        ) for k in range(n, n + 3))
    ) for n in (0, 3, 6)),
    "</table>",
    mwcollapse.Collapsible("p", 9, "YOU LOSE", attributes={"style": "font-size: 500%; font-weight: bold; text-align: center;"})
)
e.compile("notakto", mwcollapse.genStateMachine((*range(8), None, ...), transition, lambda state: (*state[0].bools, state[1], state[2]), (State(0b000010000), True, False)))
print(e)

Nim (Easy Mode) generator

#!/bin/python3
import random
import mwcollapse

nurpos = 99
def transition(state, transition):
    if state[0] != 0:
        if state[1] != 0 and transition != 0:
                return (state[0] - 1, state[1] - 1)
        elif transition == 0 and state[1] != 3:
            if state[0] & 3 == 0:
                return (state[0] - random.randrange(1, 4), 3)
            return (state[0] & -4, 3)
    return None
def stategen(state):
    return (*(n < state[0] for n in range(nurpos)), state[0] == 0 and state[1] == 3, state[0] == 0 and state[1] != 3)
stateMachine = mwcollapse.genStateMachine((0, 1), transition, stategen, (nurpos, 3))
elementContainer = mwcollapse.ElementContainer('<p class="nurpons">', *(mwcollapse.Collapsible("span", n, "[[File:Nerpawhite.png|64px|link=]]") for n in range(nurpos)), '</p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 1, "Remove one", attributes={"class": "nimbutton"}), '<span class="nobutton">Remove one</span></p>\n<p class="nimbuttons">', mwcollapse.Trigger("span", 0, "End turn", attributes={"class": "nimbutton"}), '<span class="nobutton">End turn</span></p>', mwcollapse.Collapsible("p", nurpos, "YOU LOSE", attributes={"class": "bigtexty"}), mwcollapse.Collapsible("p", nurpos + 1, "YOU [[Win|WIN]]", attributes={"class": "bigtexty"}))
elementContainer.compile("nim", stateMachine)
print(elementContainer)

Nim (Pedantic Mode) generator

#!/bin/python3
import math
import mwcollapse
import warnings

class nimstate:
    __slots__ = "piles", "prev"
    def __init__(self, piles, prev):
        self.piles = tuple(piles)
        self.prev = prev
    def __eq__(self, other):
        return False if other == None else self.piles == other.piles and self.prev == other.prev
    def __hash__(self):
        return hash(self.piles) ^ hash(self.prev)

def parity(iterable):
    p = 0
    for n in iterable:
        p ^= n
    return p

nurpos = (2, 4, 3, 5)
offsets = tuple(sum(nurpos[0:n]) for n in range(len(nurpos)))
count = offsets[-1] + nurpos[-1]

def transition(state, transition):
    l = list(state.piles)
    if transition != None:
        if (state.prev == None or transition == state.prev) and l[transition] != 0:
            l[transition] -= 1
            return nimstate(l, transition)
    elif state.prev != None and max(l) != 0:
        for n in range(1, max(nurpos) + 1):
            for i in range(len(nurpos)):
                l[i] -= n
                if l[i] >= 0 and parity(l) == 0:
                    return nimstate(l, None)
                l = list(state.piles)
        warnings.warn(f"{state.piles}, {state.prev} : {transition}")
def stategen(state):
    l = []
    for i, n in enumerate(state.piles):
        l.extend(k < n for k in range(nurpos[i]))
    l.append(max(state.piles) == 0)
    return l

stateMachine = mwcollapse.genStateMachine((*range(len(nurpos)), None), transition, stategen, nimstate(nurpos, None))
elementContainer = mwcollapse.ElementContainer(
    *(mwcollapse.Element("div",
    '<p class="nurpons">',
        *(mwcollapse.Collapsible("span", k, "[[File:Nerpawhite.png|64px|link=]]") for k in range(o, o + nurpos[i])),
    '</p>\n<p class="nimbuttons">',
        mwcollapse.Trigger("span", i, "Remove one", attributes={"class": "nimbutton"}),
        '<span class="nobutton">Remove one</span>',
    "</p>\n", attributes={"class": "pile"}) for i, o in enumerate(offsets)),
    '<p class="nimbuttons">',
        mwcollapse.Trigger("span", None, "End turn", attributes={"class": "nimbutton"}),
        '<span class="nobutton">End turn</span>',
    "</p>\n",
    mwcollapse.Collapsible("p", count, "YOU LOSE", attributes={"class": "bigtexty"}))
elementContainer.compile("nim", stateMachine)
print(elementContainer)

Kepler–Poinsot polyhedra

Subpages

Tautology.png This user is.