Introductie
Zachtronics, bekend van games als SpaceChem en Infinifactory, heeft een heuze assembly game gemaakt: Tesselated Intelligence System - 100Het is eigenlijk een puzzelgame, waarbij je assembly code moet schrijven om specifieke problemen op te lossen. Denk hierbij aan het filteren van input op minimale en maximale waardes, het omkeren van een getallenreeks, etc.
Naast het oplossen van de problemen zelf, is er natuurlijk de drang om dat in zo min mogelijk cycles, instructies of nodes te doen. De resultaten zijn direct te vergelijken met je vrienden om Steam en de rest van de community
Momenteel voor €6,99 te verkrijgen op Steam
How to play
Scott Manley heeft op Youtube een goede uitleg geplaatst:TIS-100 blinkt uit in zijn eenvoud, terwijl er toch best complexe dingen mee te maken zijn. De virtuele computer bestaat uit een twaalftal nodes geplaatst in een 4x3 grid. Elke node kan communiceren met de node links, rechts, boven en onder zich. Input wordt altijd aangeboden aan de bovenste rij nodes, en outputs zullen verbonden zijn aan de onderste rij nodes.
Nodes
Niet elke node is hetzelfde. Er zijn een paar verschillende typen:Compute nodes
Dit zijn nodes waarin je je assembly code kunt typen. Er is ruimte voor maximaal 15 instructies per node. Elke compute node voert zijn instructies uit onafhankelijk van andere nodes, en het is in weze dus een soort van multicore systeem. Na het uitvoeren van de laatste instructie zal hij automatisch weer met de eerste beginnen.
Stack nodes
Dit zijn speciale nodes waar je data naartoe kunt schrijven en vandaan kunt lezen. Elk getal dat je schrijft zal op een stack worden geplaatst, en elke leesactie zal het bovenste getal van de stack halen. Een stack node biedt zijn data automatisch aan aan alle aangrenzende nodes, en elke aangrenzende node kan ernaar schrijven
Corrupt nodes
Deze zijn niet bruikbaar en vormen eigenlijk louter een blokkade om de problemen iets ingewikkelder te maken, omdat je communicatiepaden erdoor gelimiteerd worden. Verder vormen ze een deel van de storyline, voor zover je daarvan kunt spreken.
Assembly syntax
De assembly syntax komt redelijk overeen met wat je wellicht gewend bent, en het aantal instructies is zeer gelimiteerd. Elke instructie bestaat uit een opcode, gevolgd door 0, 1 of 2 operanden. Mogelijke operanden bestaan uit registers, getallen (van -999 t/m +999), of labels in het geval van jump instructies. Wat betreft de volgorde van de operanden indien er twee zijn, dan komt eerst het bronregister en daarna het doelregister. Dit is tegengesteld van wat je wellicht gewend bent van menig echte assembly syntax. Labels definieer je met een identifier gevolgd door een dubbele punt, eventueel direct gevolgd door een instructie. Comments beginnen met een #Voorbeeld:
code:
1
2
3
4
5
6
7
| #My super leet program MOV LEFT, ACC ADD 5 JLZ Done MOV ACC, DOWN Done: MOV 45, LEFT |
Je kunt breakpoints plaatsen door een uitroepteken voor de instructie te zetten.
Registers
Er zijn in totaal 6 registers: ACC, BAK, LEFT, RIGHT, UP en DOWN. Daarnaast zijn er nog de "virtuele" registers ANY, LAST en NIL.
- ACC is de accumulator, en wordt gebruikt voor het doen van berekeningen, vergelijkingen en tijdelijke opslag.
- BAK is een backup register. Met de SAV en SWP instructies kun je data verplaatsen van ACC naar BAK en vice versa, maar hij is anderzijds niet direct aan te spreken met andere instructies.
- LEFT, RIGHT, UP en DOWN zijn port registers, waarmee je kunt communiceren met aangrenzende nodes. Deze vormen tevens een vorm van synchronisatie: een node die een waarde schrijft naar RIGHT, zal niet verder gaan met het uitvoeren van instructies voordat die waarde wordt uitgelezen door de node rechts van hem.
- ANY gebruik je om je data aan te bieden aan alle omliggende nodes, of juist om data te lezen van een willekeurige omliggende node. De eerste node die een leesactie doet zal de data verkrijgen, en vice versa. Het gedrag als er meerdere aangrenzende nodes lezen of schrijven is "implementation defined" volgens de handleiding (hint: het is weldegelijk deterministisch en hier kun je soms je voordeel mee doen
).
- LAST is nuttig in combinatie met ANY. Elke compute node onthoudt namelijk het register waar dmv ANY het laatst naar geschreven of van gelezen is. Deze kun je opnieuw aanspreken met LAST. Het is implementation defined wat er gebeurt als je LAST gebruikt voordat je ANY hebt gebruikt.
- NIL is vergelijkbaar met /dev/null
. Een leesactie van NIL zal gewoon 0 opleveren, en een schrijfactie naar NIL gooit de waarde weg. Je zal dit vooral gebruiken als doelregister bij het lezen van een van de port registers, om te kunnen synchroniseren zonder dat je verplicht bent iets met de betreffende waarde te doen.
MOV <source>, <dest>
Verplaatst data van het ene register naar het andere. Het <source> operand kan een register of een getal zijn, het <dest> operand is altijd een register.
ADD <source>
Telt een register of getal op bij de huidige waarde in ACC.
SUB <source>
Trekt een waarde of register af van de huidige waarde in ACC.
NEG
Keert het tegen van ACC om. Oftewel, ACC = -ACC.
SAV
Slaat de waarde van ACC op in BAK.
SWP
Verwisselt ACC en BAK.
JMP <label>
De eerstvolgende instructie die zal worden uitgevoerd is die direct na <label> (of de allereerste als er niets meer na <label> komt),
JEZ <label>
JNZ <label>
JLZ <label>
JGZ <label>
Conditional jump - sprint alleen naar <label> als de waarde in ACC respectievelijk: gelijk is aan 0, niet gelijk is aan 0, kleiner is dan 0, groter is dan 0.
JRO <source>
Een relatieve jump. <source> is een register of een getal. De eerstvolgende instructie is de huidige + de waarde van <source>. Dus JRO -1 springt 1 instructie terug en JRO 4 sprint 4 instructies verder. JRO LEFT leest van LEFT en springt zoveel instructies vooruit of achteruit. Een waarde van 0 zorgt ervoor dat hij naar zichzelf springt.
NOP
Een no-operation. Volgens de handleiding equivalent aan ADD NIL. Gebruik je vooral voor exacte timing, of het creëren van een juiste aantal instructies bij het gebruik van JRO.
Timing
Elke instructie kost in principe 1 cycle, met uitzondering van het schrijven naar een van de port registers met behulp van MOV. Het kost 1 cycle om zijn data aan te bieden, en dan zal hij wachten tot de data gelezen wordt (dus minstens 1 extra cycle als de aangrenzende node op dat moment aan het lezen is). Ook de input en outputs van de TIS-100 zijn hieraan gebonden, maar worden altijd direct gelezen en geschreven dus het lezen van een input of het schrijven naar een output kost altijd 2 cycles.
Achievements
![]() | RTFM View the TIS-100 manual. |
![]() | BUSY_LOOP Solve SELF-TEST DIAGNOSTIC in over 100,000 cycles. |
![]() | PARALLELIZE Solve SIGNAL AMPLIFIER in fewer than 100 cycles. |
![]() | UNCONDITIONAL Solve SIGNAL COMPARATOR without using the JGZ, JLZ, JEZ, or JNZ instructions. |
![]() | NO_BACKUP Solve SEQUENCE COUNTER without using the SWP instruction. |
![]() | NO_MEMORY Solve SEQUENCE REVERSER without writing any values to a stack memory node. |
![]() | HALT_AND_CATCH_FIRE Crash the TIS-100 with the hidden opcode. |
![]() | ILLEGAL_EAGLE Find and solve the hidden puzzle. |
![]() | 100_PERCENT_V1 Solve every puzzle in the TIS-100 SEGMENT MAP. |
![]() | 100_PERCENT_V2 Solve every puzzle in the TIS-NET DIRECTORY. |
Tips
Als je ruimte over hebt en nodes lopen niet in sync en wachten veel op elkaar, dan kan het lonen om de nodes verder uit elkaar te leggen en tussenliggende nodes te gebruiken om data door te voeren. De schrijvende node kan zijn data dan meteen kwijt en kan verder gaan, en voor de lezende node staat de data al meteen klaar als hij er langs komt. Je kunt hiermee soms grote winsten halen zonder dat je iets aan je algoritme verandert.Experimenteer met JRO, je gaat hem nodig hebben
Links
Website van de game zelf: http://www.zachtronics.com/tis-100/Steam Store: http://store.steampowered.com/app/370360
Tot slot
Het posten van jouw minimale score op een bepaald probleem en bijbehorende discussie wordt aangemoedigd[ Voor 30% gewijzigd door .oisyn op 31-08-2015 12:01 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.