Règles du jeu "Tetris. Allocation globale de mémoire


Tout ingénieux est simple. Rarement, très rarement, une telle simplicité devient une propriété mondiale, et c'est exactement ce qui s'est passé avec Tetris - un programme qui a changé la vie d'une personne en particulier, influencé l'histoire de l'industrie du jeu et apporté le bonheur à des millions de personnes. Son créateur, Alexey Leonidovich Pajitnov, n'a pas besoin d'être présenté.

Malheureusement, loin de tous les compatriotes connaissent l'histoire "mondiale" de la formation de Tetris, mais en attendant c'est un véritable roman policier, pas inférieur à n'importe quel "Santa Barbara" en termes d'intensité des passions.

En fait, l'idée graphique et logique de Tetris n'a pas été inventée par Alexei. À la fin des années 70 et au début des années 80, les puzzles du mathématicien américain Solomon Golomb ont été vendus avec succès dans le monde entier (y compris en URSS), dont le plus célèbre s'appelait Pentomino Puzzle. Leur idée était assez simple et douloureusement familière à tout contemporain - à partir de plusieurs figures qui avaient maintenant des formes familières (voir la figure ci-dessous), il fallait assembler les figures données. La connaissance fatidique d'Aleksey avec ce jeu a eu lieu au début des années 80, lorsque de tels puzzles étaient encore une curiosité.

Alexey Pajitnov a été formé comme un ingénieur soviétique ordinaire, comme des centaines de milliers de personnes en URSS. Il a travaillé dans ces années lointaines à l'Institut d'aviation de Moscou (dont de nombreux talents et des personnes célèbres). Par éducation, Alexei, comme son collègue américain susmentionné, était mathématicien, et donc, juste au début des années 80, il s'est familiarisé avec le miracle de la technologie informatique, qui était en fait inaccessible aux personnes d'autres professions. Comme vous le savez, à cette époque, les gens qui étaient indifférents aux ordinateurs n'existaient tout simplement pas - soit les gens ne les reconnaissaient pas et ne les considéraient pas comme plus significatifs que les meubles, soit ils tombaient instantanément amoureux. Inutile de dire que Pajitnov - non sans son propre plaisir - est devenu un adhérent du deuxième groupe. Selon ses souvenirs, une personne laissée seule avec un ordinateur s'est transformée en une sorte de vieux Hottabych et était capable de son propre petit miracle local.

Dès que l'occasion s'est présentée à Alexei, il a déménagé de l'institut au centre informatique de l'Académie des sciences, faisant d'une pierre deux coups : il a entrepris un travail qui l'intéressait vraiment et a eu accès au plus puissant technologie informatique qui existait à l'époque dans l'Union. Au nouvel endroit, Pajitnov s'est attaqué aux problèmes de création d'intelligence artificielle, d'infographie et de problèmes de reconnaissance vocale par ordinateur. A cette époque, il avait 29 ans. Par conséquent, il n'y avait rien d'étrange à ce que, pendant son temps libre, il s'adonne à l'écriture de petits jouets très simples. Le moment de sa transition vers un nouveau lieu de travail, par un hasard chanceux, a coïncidé avec une passion pour les puzzles Golomb - et dans la tête brillante d'un ingénieur russe pour la première fois l'idée de créer une version informatique s'est levé. Pajitnov a assez fortement complété l'idée - il était nécessaire d'assembler les «figures dans un verre» en temps réel, et les figures se composaient de cinq éléments (Pentamino - du grec «Penta» - cinq), et, selon l'idée, devaient tourner autour de leur propre centre de gravité pendant la chute. Hélas, les "cerveaux" électroniques des machines de cette époque se sont avérés trop faibles pour mettre en œuvre l'idée de cerveaux humains - il n'y avait tout simplement pas assez de ressources pour l'ordinateur "Pentamino". Pajitnov décide alors de réduire à quatre le nombre de blocs qui composaient les chiffres en baisse, incarnant ainsi le "Tetramino" moins gourmand en ressources (du grec "Tetra" - quatre). Le nom abrégé "Tetris" est resté un peu plus tard.

Simple, en général, l'idée a donné par la suite des résultats surprenants. Aleksey a écrit rapidement la première version du jeu - prenant comme base sept chiffres, qui sont devenus plus tard l'ensemble standard de Tetris, il a programmé l'épine dorsale du jeu en deux semaines. Dans ce document, même les images graphiques de personnages ne sont pas tombées dans le «verre», mais leurs homologues textuels - constitués d'espaces, de crochets, etc. Tout semblait étrangement primitif - le jeu a été créé sur la base du langage "folk" Pascal et sur l'ordinateur "Electronics-60", qui n'avait même pas de moniteur normal. Mais le jeu a fonctionné, et comment cela a fonctionné!

Au début, Tetris n'allait pas au-delà du même laboratoire. Pajitnov, après avoir testé la version initiale sur lui-même et ses collègues, a attiré un camarade d'armes, Vadim Gerasimov, âgé de seize ans, dans l'affaire, et en deux mois, la première version graphique et couleur de Tetris a été créée, qui avait contrôles sains et petits équipements, comme une table des enregistrements. Un point importantétait le fait que Gerasimov a en fait aidé à "porter" le jeu sur la plate-forme PC, qui gagne en popularité chaque jour. Avec le PC, les premiers lecteurs de disque 5,25 "ont également gagné en popularité, de sorte que le problème de la "réplication" initiale a été résolu assez rapidement - après avoir copié le plaisir résultant sur des disquettes, Alexey et ses camarades l'ont diffusé en marge de la recherche institut. Un ami a copié d'un ami, puis a donné trois autres amis à copier, et lentement la «lettre du bonheur» électronique s'est répandue dans la capitale et en est sortie. Le jeu est devenu célèbre en URSS.

C'était en 1985, de plus en plus de critiques chaleureuses arrivaient sur Tetris, et progressivement Aleksey était enclin à penser que les pays étrangers devraient également se familiariser avec sa création. Les premiers étrangers qui goûtèrent aux délices du programme du génie russe furent les budapestois de l'Institut des problèmes cybernétiques, avec lesquels l'Institut de recherche collabora alors à l'un des nombreux programmes des « peuples frères ». La version PC de Tetris a été divulguée à l'étranger, et déjà en Hongrie, elle a été adaptée aux besoins des plates-formes alternatives - Commodore C64 et Apple 2. Heureusement pour Alexei, à ce moment-là, Robert Stein, un Hongrois d'origine anglaise, visitait l'Institut , dont les avantages ne s'arrêtaient pas au seul passeport étranger. Stein, par une coïncidence fatale, s'est avéré être le propriétaire de son propre studio de jeux Andromeda. Un homme d'affaires expérimenté a immédiatement senti le potentiel du jouet. Sans remettre les choses à plus tard, Stein propose d'acheter les droits de toutes les versions du jeu à la fois: sur Apple 2 et C64 des Hongrois, et la version PC, respectivement, des Russes. Aussitôt dit, aussitôt fait : Robert télégraphie à l'Académie des Sciences de l'URSS, et propose aux Russes d'acheter les droits de "Tetris" sans qu'aucun montant précis n'ait encore été annoncé. Qui refuserait un tel cadeau du destin ? Pajitnov n'était pas de ceux qui ont raté sa chance, et il est d'accord.

A cette époque, Stein retourne à Londres et commence à chercher des marchés pour le jeu, et Londres est déjà (selon les normes du milieu des années 80) l'étranger lointain avec tous les obstacles qui en découlent pour l'époque. Par conséquent, en raison de retards politiques, le Hongrois ne reçoit un télex historique avec la réponse de Pajitnov qu'après un mois et demi. Cependant, au lieu d'attendre une réponse, puis de partir humainement en voyage d'affaires et de signer un contrat, le Hongrois ne reste pas les bras croisés, il cherche frénétiquement quelqu'un pour fusionner le futur hit. Il propose d'abord une version de Tetris à ceux qui sont plus proches - l'anglais Mirrorsoft. Le propriétaire de cette société à l'époque était le magnat des médias Robert Maxwell, propriétaire de la société de presse britannique Mirror Newspaper Group et de l'américain Macmillan. Plus tard, il dira encore son mot de poids dans cette histoire. Les messieurs de Mirrorsoft se sont familiarisés avec Tetris, ont joué un peu et ... ont douté de manière blasphématoire de la capacité du produit à bien se vendre. Le projet a été envoyé pour un test alternatif à leurs homologues américains de Spectrum Holobyte. Bien versés dans les jeux et les moyens de gagner de l'argent à partir de rien, les Américains ont vu un potentiel considérable dans le programme. Les Yankees ont communiqué leur opinion aux Britanniques, qui étaient d'accord avec Stein. Le résultat de ce saute-mouton fut un contrat entre Mirrorsoft et Andromeda, estimé à un montant dérisoire de 3 000 livres et un pourcentage flottant des revenus (7 à 15 % selon le nombre d'exemplaires vendus). Et Stein a fait tout cela, n'ayant pas de droits de Pajitnov lui-même à ce moment-là!

A cette époque, Alexei Leonidovich était à Moscou, dans l'ignorance totale de ce qui se passait avec sa progéniture. Par conséquent, lorsqu'il reçut un deuxième message de Stein, dans lequel il offrait à Pajitnov les trois quarts de tous ses revenus, plus une bonne somme d'argent, sa joie ne connut aucune limite. Il n'a pas diminué même lorsque "l'après" hongrois a proposé de payer une partie de l'avance avec des ordinateurs Commodore, puisqu'il était en quelque sorte le distributeur officiel de cette société. Alexey semblait disposé à un tel développement des événements, mais il n'a pas encore pris de décision définitive. Un point important dans ces négociations reste qu'il ne s'agissait que de la version PC de Tetris. À l'hiver 1985, Stein vient à Moscou afin de documenter la relation, mais il ne signe jamais rien. Les Russes (représentés par des représentants individuels de l'Académie des sciences) demandent banalement plus que ce qu'il leur a offert dans ses télégrammes. Le Hongrois a dû repartir sans rien.

En attendant, les événements se déroulent selon un scénario imprévisible. Les Américains de Spectrum Holobyte, qui possédaient une version du jeu des Britanniques de Mirrorsoft, dont ils auraient détenu les droits vendus par Stein, ont pris au sérieux le programme. Les événements se déroulent pendant les années des conséquences de la guerre froide, la confrontation entre le capitalisme et le socialisme est perceptible à l'œil nu. Et dans ce contexte, le jeu des Russes avait déjà l'air indescriptiblement attrayant, quel que soit le contenu. C'est en accord avec leurs idées sur les Russes que les Américains refaçonnent le design du jeu, laissant les mécaniques inchangées. Le fond noir est remplacé par des écrans de veille lubok, "Kalinka-Malinka" et "Eh, uhny !" sonnent comme une ambiance, des éléments militaires apparaissent ici et là, des portraits de Youri Gagarine scintillent et l'apothéose devient un écran de veille dans lequel devant le cathédrale Saint-Basile, Matthias Rust atterrit dans son célèbre avion Cessna ! En un mot, le jeu a changé et d'un programme créé par un passionné, il s'est transformé en un produit commercial à part entière, bien qu'occidental.

Stein n'avait d'autre choix que d'obtenir rapidement un contrat des Russes. Il avait déjà 87 ans et en Occident, ils se préparaient à sortir une version révisée de Tetris, estimant qu'ils avaient toutes les raisons pour cela (les droits achetés à Stein). Et il n'y avait tout simplement aucune raison. Le propriétaire d'Andromeda a été ballotté entre le marteau et l'enclume - il n'avait toujours pas les droits de l'auteur, et en même temps, il ne savait pas comment informer ses collègues occidentaux de la nécessité de retarder le jeu presque terminé. En conséquence, la lâcheté l'a emporté et, en 1988, une sortie a frappé l'Amérique et l'Angleterre.

Tetris a immédiatement gagné en popularité et a commencé à être vendu en très bonne circulation, gagnant progressivement de plus en plus en popularité. Moins d'un an plus tard - et "Tetris" recevra plusieurs prix importants de l'American Developers Association Logiciel. En particulier, en tant que meilleur logiciel grand public, meilleur développement original et meilleur programme de divertissement.

Aleksey, quant à lui, a quitté l'Académie des sciences et a rejoint la société nouvellement formée Electronorgtechnika (ELORG). Là, on lui a expliqué ce qu'il faisait de mal et pourquoi son produit avait été diffusé en Occident sans sa participation. Pajitnov est d'accord avec les arguments de poids de collègues plus expérimentés. Inutile de dire qu'après cela, ils se sont littéralement empilés sur Stein, exigeant de résoudre la situation devenue incontrôlable. La pression de la Russie a été aggravée par des actions similaires de la part des compatriotes de Stein. Surtout après que le match a remporté tant de récompenses et que les journalistes omniprésents de CBS ont déterré le génie russe et l'ont interviewé, clarifiant beaucoup de choses. Le Hongrois malhonnête n'a eu d'autre choix que de signer le satané traité en mai 1988 aux conditions des Russes. Et encore une fois, uniquement sur la version PC du jeu. Pendant ce temps, les événements ne se sont pas arrêtés. Western Tetris a acquis une renommée et des récompenses, et s'est déplacé plus loin dans le monde. Dans le même temps, les progrès technologiques évoluaient également - le concept de «jeu» et l'ordinateur commençaient à se délimiter, et l'ère des premières consoles avançait lentement dans le monde ...

Sentant où le vent soufflait, Mirrorsoft a exigé que Stein achète les droits des versions console et arcade de Tetris aux Russes, et entre-temps, elle a elle-même vendu les droits de la version arcade (sans aucune raison) à Atari, un société assez connue dans certains milieux, qui les revend aussitôt au japonais Sega. Comment! Il convient également de mentionner que Stein, qui a tenté d'acquérir les droits convoités d'ELORG, n'a rien obtenu. En attendant, la version PC de Tetris sort au Japon, ainsi que (et surtout) sa version Famicom sur la console de Nintendo, qui finit par diverger au Pays du Soleil Levant à plus de deux millions d'exemplaires ! Pour expliquer comment cela est devenu possible, il faut creuser un peu plus dans le passé.

Il convient de dire quelques mots sur le préfixe "tycoon". À la fin des années 70, Nintendo commence à prendre de l'ampleur et lance un produit révolutionnaire à l'époque - un jouet de poche Game & Watch (plus tard, nous avons eu son analogue - "Just you wait!"), Qui devient immédiatement un best-seller. Un peu plus tard (84), Nintendo lance le produit GameBoy, qui est encore plus important pour son développement, et cherche juste un jeu qui peut apporter une super popularité à la console de poche. Au moment où Tetris s'est répandu dans le monde entier, la relation entre Nintendo et Atari était comme un chat et un chien en raison de certaines "configurations" majeures sur le marché américain et des litiges prolongés qui ont suivi. Et encore (pour la énième fois !) Sa Majesté la chance intervient dans la partie. En juin 88, le président de la division américaine de Nintendo, Minoru Arakawa, a accidentellement vu un ordinateur avec Tetris installé lors d'une exposition d'appareils électroménagers. Il a immédiatement ressenti le charme du divertissement et s'est enflammé du désir d'acquérir les droits d'une version portable (console) du jouet. Il a commencé à découvrir à qui ils appartenaient ce moment, et sont allés chez Atari, où ils croyaient très sincèrement que tous les droits leur appartenaient, puisqu'ils les avaient "honnêtement" achetés à Mirrorsoft. L'oie n'est pas l'amie du cochon, Arakawa comprend qu'il est inutile de parler à Atari. Cependant, un coup de chance frappe à nouveau à la porte et oppose Arakawa à Hank Rogers.

Hank Rogers est l'un des personnages clés de toute cette histoire. Le propriétaire d'une petite entreprise japonaise, Bullet Proof Software, est la personne à qui Spectrum Holobyte a vendu les droits de publication de Tetris sur le marché japonais. Vrai, uniquement pour sa version PC, puisque Atari avait tous les autres droits à cette époque. Mais l'entreprenant Yankee savait frapper aux portes. Très vite, il parvient à arracher à Atari les droits de la version console pour le même marché. Et presque à ce moment-là, il rencontre Arakawa !

M. Arakawa a immédiatement pris le taureau par les cornes. Il avait besoin de Tetris. La sortie de la version Famicom a été un événement marquant dans l'histoire de l'entreprise, mais au moment des événements qui se sont déroulés, la version portable du jeu était beaucoup plus précieuse pour Arakawa, en tant que candidat le plus approprié pour l'extension Gameboy. De plus, il était prêt à payer des prix exorbitants pour les droits à cette option. Rogers n'était par nature pas une personne stupide et soupçonnait que la situation n'était pas propre avec les droits, alors il décide de retracer toute la chaîne des titulaires de droits d'auteur, en commençant par la source. En février 1989, il se rend à Moscou. Stein, à qui Rogers avait imploré les droits d'une version portable peu de temps auparavant, sentit qu'il sentait la friture et s'y dirigea de toute urgence. La troisième personne à se rendre à Moscou est Kevin Maxwell, le fils du magnat des médias qui possédait Mirrorsoft et (a priori) Spectrum Holobyte.

Quelle ne fut pas la surprise de Rogers (qui est venu voir Alexei et lui a montré la version japonaise de Tetris pour la Famicom en guise de présentation) lorsqu'il a découvert que personne n'avait vendu de droits à qui que ce soit et qu'ils n'avaient jamais entendu parler de Nintendo ici ! Un analogue complet de la Famicom, connu sous le nom de Dendy, apparaîtra en Russie bien plus tard, alors que personne ne sait rien des consoles miracles en URSS. Cependant, Pajitnov avait bien plus de raisons d'être surpris : il s'avère que son jeu « marche » déjà partout dans le monde et dans toutes les variantes, mais il n'en a toujours rien reçu. Profitant du moment, Rogers signe un contrat pour lui transférer les droits de la version portable du jeu et promet de revenir avec un représentant de Nintendo, qui était puissant à l'époque, par souci de droits authentiques pour la console. version.

Stein, qui est arrivé un peu plus tard, a été brièvement expliqué qui il était et a montré le contrat signé avec lui au tout début, où il était clairement dit du transfert des droits uniquement vers la version PC. Le Hongrois n'a pas prouvé qu'il n'était pas un chameau et a accepté toutes les accusations. Comme la confiance en son ami était déjà ébranlée, tout ce qu'il put retirer de la visite fut de lui transférer les droits de la version arcade du jeu (pour les machines à sous), et pour "très cher". Sur ce, il est parti.

Un peu plus tard, le fils de Maxwell apparaît dans ELORG. Des camarades ont poussé une cartouche de jeu sous son nez, où le nom du jeu et le nom de la société distributrice sont lus dans un anglais compréhensible: «Mirrorsoft». Ensuite, ils posent la question: "Pour quelle raison cette cartouche existe-t-elle?". Le garçon, qui ne possédait pas toutes les informations, ne peut pas donner d'explications claires et quitte la maison dans un état abasourdi. Dès qu'il arrive en Angleterre et informe son père des résultats de la rencontre, la pression commence contre ELORGE. Réalisant que les positions de Mirrorsoft et d'Atari sont menacées, Robert Maxwell utilise toute la puissance du réseau d'information qu'il a créé, fait du bruit et porte ainsi le problème au niveau du gouvernement. Selon des informations non confirmées par des responsables, le gouvernement de Grande-Bretagne et l'URSS décident d'aider Maxwell, dans le but duquel la pression sur ELORG de la patrie augmente. Cependant, les Russes ne "cédent" jamais - et voici pourquoi.

Parce que Rogers n'a pas triché. Pendant que Maxwell dénouait son affaire, Rogers - incognito, dans le plus grand secret (pour que les concurrents d'Atari ne le flairent pas) amène Arakawa et son conseiller juridique Howard Lincoln (qui devint le futur président de Nintendo) à Moscou. Dans la capitale, ils signent le contrat le plus important. Le 21 mars 1989, le plus grand acteur du marché du divertissement électronique a perdu tous les droits sur Tetris (pour le marché de la vidéo) pour un montant que des analystes indépendants estiment entre 3 et 5 millions de dollars. En cours de route, après de longs litiges, de graves dommages ont été infligés au concurrent de Nintendo, Atari. Des hommes d'affaires prévoyants ont fait d'une pierre deux coups.

Pajitnov lui-même a reçu très peu de cet argent. Certes, il y avait des rumeurs selon lesquelles le gouvernement de l'URSS aurait donné à Alexei "Pour les services à la patrie" des choses aussi luxueuses que le 286e ordinateur et un appartement entier à Moscou.

Tetris est devenu un super hit de tous les temps et de tous les peuples. Grâce à lui, dans les premières années de son existence, la GameBoy s'est vendue à plus de 30 millions d'exemplaires, et environ 15 millions de cartouches avec le programme ont été vendues.Par la suite, la GameBoy est devenue la console la plus vendue de l'histoire du divertissement électronique (plus de 100 millions de consoles officiellement vendues) . Tetris lui-même a rapporté à Nintendo, selon diverses estimations, de 2 à 3 milliards de dollars de bénéfice net, en tenant compte de tous les ports, versions et royalties. Au cours des 20 années de son existence, tous les types de Tetris (y compris les statistiques officielles, les appareils électroniques et les ventes illégales) se sont répandus dans le monde entier dans un tirage fantastique, qui est estimé à un quart de milliard d'exemplaires. Inutile de dire qu'aucun autre jeu n'a pu atteindre une telle popularité. Oui, et il est peu probable que cela soit jamais possible.

Le sort ultérieur de Pajitnov n'a pas été facile, mais intéressant. Réalisant que vous pouvez gagner votre vie en faisant ce que vous aimez, en 1989, avec son ami Vladimir Pokhilko et avec la participation du même Hank Rogers, il a fondé le studio AnimaTek, dont l'activité principale est le développement de divers puzzles informatiques et problèmes d'intelligence artificielle dans les jeux. Au début, les clients d'AnimaTek étaient des entreprises russes bien connues telles que Paragraph, Doka, Dialog et un certain nombre de petites entreprises. Au total, en 1991, Alexey et ses camarades avaient développé ou participé au développement de plus de trois cents jeux ! Les développements d'AnimaTek ont ​​ensuite été utilisés dans des projets aussi connus que Age of Empires de Microsoft et final Fantasy Tactique (Carré).

Cependant, au début des années 90, le marché post-soviétique des jeux était inexistant et, afin de recevoir une rémunération adéquate pour son travail, Pajitnov a déménagé en Amérique. Le siège social d'AnimaTek est transféré à San Francisco et continue de se concentrer sur le secteur des jeux. Vladimir Pokhilko n'a pas quitté son ami et a également déménagé aux États-Unis, où il est resté longtemps le directeur d'AnimaTek. Soit dit en passant, un peu plus tard, un autre personnage de notre histoire s'installe en Amérique - Vadim Gerasimov, grâce aux efforts duquel Tetris est arrivé une fois sur l'IBM PC. Cependant, Gerasimov a renoncé à ses droits sur Tetris en 1987, donc son destin ultérieur n'a rien à voir avec le jeu.

Aleksey a quitté la direction de l'entreprise à Pokhilko, et dans le même 91 (et encore avec la participation de Rogers) il a créé une campagne avec le nom révélateur "Tetris", où il a développé divers types de puzzles, y compris ceux basés sur le classique Tétris. Et c'est à ce stade que Pajitnov commence enfin à recevoir de l'argent des jeux qu'il a développés. Le destin d'AnimaTek en Amérique n'est pas facile. Les Russes publient les uns après les autres des jeux de genres différents, mais aucun d'entre eux n'arrive à se vendre en grand nombre. En particulier, la société ignore complètement le projet pionnier El-Fish (quelque chose comme un aquarium informatique), qui, en fait, était la première animation par ordinateur de l'entreprise. Et puis l'apogée du marché du divertissement électronique commence, et la société Pajitnov, qui n'est pas en mesure de rivaliser avec les développeurs de jeux professionnels, bascule les flèches vers les rails des programmes de modélisation graphique 3D. En particulier, la société a produit des produits tels que World Builder (un programme de modélisation de paysages en trois dimensions) et Caviar (travaillant avec les technologies voxel).

Pajitnov lui-même en 1996 va "sous l'aile" du tout-puissant Microsoft afin de faire ce qu'il aime le plus - les puzzles. Désormais, il devient game designer-consultant, et sous sa houlette se trouve une petite équipe soudée d'une dizaine de personnes. Le premier résultat de leur activité commune est la sortie en 1997 Le puzzle Collection, qui est un ensemble de puzzles de nature très différente. Si certains d'entre eux impliquaient exclusivement des cellules cérébrales grises, d'autres étaient conçus pour une certaine vitesse de réaction, la capacité de prendre rapidement les bonnes décisions, etc. Et en septembre 1999, Pandora Box est sorti - une collection de sept puzzles avec un titre intrigant, une sorte de scénario et une belle performance visuelle. Différentes périodes (de l'Égypte ancienne aux gratte-ciel modernes), des photographies de haute qualité et des reproductions d'artistes et de sculpteurs célèbres - tout cela a servi de toile de fond à d'excellents jeux intelligents. De plus, dans les premier et deuxième cas, Microsoft n'a pas hésité à recourir à des relations publiques supplémentaires - les jeux contenaient la ligne "du créateur de Tetris" ...

Après la sortie de Pandora's Box, les yeux d'Alexey se sont tournés vers Internet. Sur le serveur officiel de Microsoft, il y avait même un département spécial de la MSN Game Zone - Mind Aerobics. En fait, il s'agit du même ensemble d'énigmes statiques, mais avec quelques innovations, principalement liées aux modes de jeu. En particulier, les gens ont eu la possibilité de s'affronter sur Internet, de monter sur le haut du podium ou simplement de suivre les «combats» de connaissances. Le jeu est très populaire depuis longtemps.

Telle est la difficile histoire d'Alexei Pajitnov. Maintenant, il est une personne riche et respectée, un employé du célèbre Microsoft, vit et travaille aux États-Unis. Le génie russe a sorti ses jeux plusieurs fois - principalement des puzzles, des produits très intéressants et solides. Son Hexic HD est inclus avec Xbox Live Arcade pour Xbox 360, et les utilisateurs de PC ont récemment pu découvrir son dernier titre, Dwice (décrit dans notre revue Crescent Casuals). Mais ils n'étaient pas destinés à connaître à nouveau un tel succès qu'avec Tetris. Cependant, aucun autre jeu au monde ne pourrait même se rapprocher de Tetris en termes de popularité.

Ce projet a commencé en réponse à une question Stackexchange :
C'est un problème théorique - il n'a pas de réponse simple ni triviale.

Dans Game of Life de Conway , des constructions telles que des métapixels existent, qui permettent au Game of Life de simuler n'importe quel système de règles similaire à Life. De plus, le jeu de la vie est connu pour être complet de Turing.

Votre tâche est de créer un automate cellulaire qui utilise les règles du jeu de la vie de Conway et vous permet de jouer à Tetris.

Le programme doit recevoir une entrée en changeant manuellement l'état de l'automate à une certaine génération, représentant une interruption (c'est-à-dire déplacer une pièce à gauche ou à droite, tourner, descendre ou générer aléatoirement une nouvelle pièce à placer sur le terrain). Un certain nombre de générations est considéré comme un temps d'attente. Le résultat du jeu est affiché quelque part dans la machine. Le résultat obtenu devrait ressembler visuellement au champ du vrai Tetris.

Votre programme sera jugé selon les critères suivants, dans cet ordre (les critères inférieurs s'ajoutent aux critères supérieurs) :

  • Taille du rectangle englobant - la boîte rectangulaire avec la plus petite zone qui contient complètement la solution gagne.
  • Le moins de changements à l'entrée - remporte la solution avec le moins de cellules (dans le pire des cas pour votre automate) à configurer manuellement en tant qu'interruption.
  • Exécution la plus rapide - remporte la solution avec le moins de générations pour avancer d'un cycle de simulation.
  • Nombre initial de cellules vivantes - le plus petit nombre gagne.
  • Première publication - remporte le tout premier message avec la solution.

L'idée centrale de ce projet était abstraction. Au lieu de développer directement Tetris dans le jeu de la vie, nous avons élargi l'abstraction que nous avons créée étape par étape. À chaque couche, nous nous sommes éloignés de plus en plus des complexités de la "Vie" et nous nous sommes rapprochés de la création d'un ordinateur qui serait aussi facile à programmer que n'importe quel autre.

Tout d'abord, nous avons utilisé les métapixels OTCA comme base pour l'ordinateur. Ces métapixels peuvent émuler toutes les règles du jeu Life-like. Wireworld et l'ordinateur Wireworld ont été des inspirations importantes pour ce projet, et nous avions pour objectif de créer un design similaire basé sur des métapixels. Bien qu'il ne soit pas possible d'émuler Wireworld à l'aide de métapixels OTCA, il est possible de définir différentes règles pour différents métapixels et de créer des constructions de métapixels qui fonctionnent comme des fils Wireworld.

L'étape suivante a été la création de nombreuses portes logiques fondamentales qui peuvent être utilisées comme base d'un ordinateur. À ce stade, nous traitons déjà de concepts similaires aux concepts de conception de processeurs du monde réel. Voici un exemple de porte OU, chaque cellule de cette image est en fait un métapixel OTCA entier. Vous voyez des "électrons" (chacun représentant un seul bit de données) entrer et sortir de la porte. Vous pouvez également voir tous les types de métapixels que nous avons utilisés pour créer l'ordinateur : B/S - fond noir, B1/S - bleu, B2/S - vert, B12/S1 - rouge.

A partir de là, nous avons développé l'architecture du processeur. Nous avons passé beaucoup de temps à développer une architecture à la fois compréhensible et facile à mettre en œuvre. L'ordinateur Wireworld utilise une architecture rudimentaire déclenchée par le transport, tandis que notre projet utilise une architecture RISC beaucoup plus flexible avec plusieurs opcodes et modes d'adressage. Nous avons créé le langage d'assemblage QFTASM (Quest for Tetris Assembly), qui contrôlait la fabrication du processeur.

De plus, notre ordinateur est asynchrone, ce qui signifie qu'il n'est pas contrôlé par une horloge globale. Lors de la transmission au sein de l'ordinateur, les données sont accompagnées d'un signal de synchronisation. Cela signifie que nous n'avons besoin que de suivre les horaires informatiques locaux, et non mondiaux.

Voici une illustration de notre architecture de processeur :

Désormais, il ne nous reste plus qu'à implémenter Tetris dans un ordinateur. Pour faciliter les choses, nous avons développé plusieurs façons de compiler un langage de haut niveau dans QFTASM. Nous avons langue de base Cogol, un second langage plus avancé, est en cours de développement, et nous construisons enfin le backend GCC. Maintenant, le programme Tetris est écrit en Cogol et compilé à partir de celui-ci.

Une fois le code QFTASM Tetris final généré, les étapes suivantes consistaient à assembler à partir de ce code la ROM appropriée, puis des métapixels au jeu de la vie sous-jacent, ce qui compléterait notre travail.

Lancer Tetris

Ceux qui veulent jouer à Tetris sans jouer avec le compilateur peuvent exécuter le code source de Tetris dans l'interpréteur QFTASM. Pour voir le jeu entier, spécifiez les adresses RAM affichées 3-32. Voici un permalien pour plus de commodité : Tetris dans QFTASM.

Caractéristiques de jeu:

  • Les 7 tétrominos
  • Mouvement, rotation, descente en douceur des chiffres
  • Effacer les lignes et marquer des points
  • Afficher la figure suivante
  • L'entrée du joueur ajoute du caractère aléatoire
Affichage
Notre ordinateur représente le champ de Tetris sous la forme d'une grille en mémoire. Les adresses 10-31 affichent le champ, les adresses 5-8 la figure suivante, l'adresse 3 contient le score.

Saisir
L'entrée dans le jeu se fait en éditant manuellement le contenu de l'adresse 1 dans la RAM. Lors de l'utilisation de l'interpréteur QFTASM, cela signifie une écriture directe à l'adresse 1. Voir "Écriture directe dans la RAM" sur la page de l'interpréteur. Chaque mouvement nécessite la modification d'un seul bit de RAM et ce registre d'entrée est automatiquement réinitialisé après la lecture d'un événement d'entrée.

mouvement de valeur
1 rotation dans le sens inverse des aiguilles d'une montre
2 restants
4 vers le bas (abaissement doux)
8 à droite
16 rotation dans le sens des aiguilles d'une montre

Système de notation
Le joueur reçoit un bonus pour avoir supprimé plusieurs lignes en un seul coup.

1 ligne = 1 point
2 lignes = 2 points
3 lignes = 4 points
4 lignes = 8 points

Partie 2 : OTCA Metapixel et VarLife

Métapixel OTCA

Varlife

J'ai créé un simulateur en ligne des règles des jeux Life-like, dans lequel vous pouvez définir le comportement de n'importe quelle cellule conformément à toutes les règles similaires aux règles de "Life". J'ai nommé le simulateur Variations of Life. Par souci de brièveté, ce nom a ensuite été changé en "VarLife". En voici une capture d'écran (lien vers le simulateur : http://play.starmaninnovations.com/varlife/BeeHkfCpNR) :

Caractéristiques notables :

  • Bascule les cellules entre les états "vivant" / "mort" et peint le champ selon diverses règles.
  • La possibilité de démarrer et d'arrêter une simulation, une étape à la fois. Il est également possible d'exécuter un certain nombre de pas à vitesse maximale ou plus lentement, avec la vitesse réglée en battements/s et ms/battement.
  • Il a la capacité de supprimer toutes les cellules vivantes ou de réinitialiser complètement le champ à un état vide.
  • Il peut modifier la taille du champ et des cellules, et également permettre une convolution toroïdale horizontale et/ou verticale.
  • Les liens permanents (qui encodent toutes les informations de l'url) et les url courtes (parce qu'il y a parfois trop d'informations, mais elles sont quand même utiles).
  • Ensembles de règles avec B/S, couleurs et caractère aléatoire facultatif.
  • Et la dernière chose est le rendu gif !
La fonction render-to-gif est ma préférée car elle a pris beaucoup de temps à mettre en œuvre. C'était vraiment cool quand je l'ai finalement terminé à sept heures du matin. Avec lui, vous pouvez facilement partager des conceptions VarLife avec d'autres personnes.

Le schéma principal de VarLife

Au total, l'ordinateur VarLife n'a besoin que de quatre types de cellules ! Il y a huit états au total, en prenant en compte les états de "mort" / "vivant":
  • B/S (noir/blanc) qui sert de tampon entre tous les composants car les cellules B/S ne peuvent jamais être vivantes.
  • B1/S (bleu/cyan) est le principal type de cellule utilisé pour la propagation du signal.
  • B2/S (Vert/Jaune) - Principalement utilisé pour contrôler les signaux en les protégeant de la rétropropagation.
  • B12/S1 (rouge/orange) - utilisé dans certaines situations particulières, comme lors du croisement de signaux et du stockage d'un bit de données.
Utilisez cette URL courte pour ouvrir VarLife avec les règles déjà encodées : http://play.starmaninnovations.com/varlife/BeeHkfCpNR .

conducteurs

Il existe plusieurs modèles de conducteurs différents avec des caractéristiques différentes.

C'est le conducteur le plus simple et le plus basique de VarLife, une bande de bleu délimitée par des bandes de vert.

C'est un conducteur unidirectionnel. C'est-à-dire qu'il détruira tous les signaux essayant de passer dans la direction opposée. De plus, c'est une cellule plus étroite que le conducteur principal.

Il existe également des conducteurs diagonaux, mais ils ne sont presque jamais utilisés.

Passerelles

En fait, il existe de nombreuses façons de créer chaque passerelle individuelle, donc je ne montrerai qu'un exemple de chaque type. Le premier gif montre les portes ET, XOR et OU, respectivement. L'idée de base est que la cellule verte agit comme un ET, la cellule bleue agit comme un XOR et la cellule rouge agit comme un OU, et toutes les autres cellules autour d'elles assurent simplement la bonne transmission.

La passerelle AND-NOT (ANT en abrégé) s'est avérée être un composant essentiel. Cette passerelle transmet un signal de A si et seulement s'il n'y a pas de signal de B. C'est-à-dire "A ET PAS B".

Bien que ce ne soit pas tout à fait passerelle, mais la tuile d'intersection de conducteur est très importante et utile.

Au fait, il n'y a pas de passerelle NOT ici. En effet, sans signal d'entrée, une sortie constante doit être produite, ce qui ne fonctionne pas très bien avec les nombreux timings requis par le matériel informatique moderne. Mais en tout cas, on a réussi à s'en passer.

De plus, de nombreux composants ont été délibérément conçus pour s'adapter à une boîte englobante de 11 par 11 ( tuile), dans lequel les signaux prennent 11 cycles à partir du moment où ils entrent dans la tuile pour sortir de la tuile. Cela rend les composants plus modulaires et plus faciles à câbler ensemble sans avoir à ajuster les conducteurs pour s'adapter à l'espace ou aux délais.

Vous pouvez en savoir plus sur d'autres portes recherchées/créées lors de l'étude des composants de circuit dans le post PhiNotPi : Building Blocks : Logic Gates.

Composants de retard

Lors du processus de conception de matériel informatique, KZhang a proposé de nombreux composants de retard illustrés ci-dessous.

Délai de 4 bar :

Délai pour 5 cycles :

Retard de 8 bars (trois points d'entrée distincts) :

Délai pour 11 cycles :

Délai pour 12 barres :

Retard pour 14 barres :

Délai de 15 cycles (vérifier en comparant avec ceci) :

Alors, voici les principaux composants des circuits VarLife ! Pour les descriptions des principaux circuits de l'ordinateur, voir la partie suivante écrite par KZhang !

Partie 3 : équipement

Grâce à notre connaissance des passerelles logiques et de la structure globale du processeur, nous pouvons commencer à concevoir tous les composants d'un ordinateur.

Démultiplexeur

Le démultiplexeur, ou démultiplexeur, est un composant essentiel de la ROM, de la RAM et de l'ALU. En fonction des données de sélecteur données, il dirige le signal d'entrée vers l'un des nombreux signaux de sortie. Il se compose de trois parties principales : un convertisseur série-parallèle, un moniteur de signal et un séparateur d'horloge.

Nous commençons par convertir les données du sélecteur série en "parallèles". Cela se fait en divisant et en retardant stratégiquement les données de sorte que le bit de données le plus à gauche croise le signal d'horloge dans le carré 11x11 le plus à gauche, le bit de données suivant croise le signal d'horloge dans le carré 11x11 suivant, et ainsi de suite.

Bien que chaque bit de données soit émis vers chaque carré 11x11, chaque bit de données ne traversera le signal d'horloge qu'une seule fois.

Ensuite, nous vérifions si les données parallèles correspondent à l'adresse donnée.
Nous faisons cela avec des portes AND et ANT pour les données d'horloge et parallèles. Cependant, nous devons nous assurer que les données parallèles sont également sorties afin qu'elles puissent être comparées à nouveau. Voici les passerelles que j'ai fini par créer :

Enfin, nous divisons simplement le signal d'horloge, connectons plusieurs testeurs de signal (un pour chaque adresse/sortie) et nous nous retrouvons avec un multiplexeur !

ROM

La ROM doit prendre une adresse en entrée et envoyer une instruction à cette adresse en sortie. On commence par utiliser un multiplexeur pour envoyer un signal d'horloge à l'une des instructions. Ensuite, nous devons générer un signal en utilisant les touches de plusieurs conducteurs et portes OU. Toucher les fils permet au signal d'horloge de traverser les 58 bits de l'instruction et garantit également que le signal généré (toujours parallèle) se déplace à travers la ROM vers la sortie.

Ensuite, nous avons juste besoin de convertir le signal parallèle en série et sur cette ROM, il sera prêt.

Actuellement, la ROM est générée en exécutant un script Golly qui transfère le code d'assemblage du presse-papiers vers la ROM.

SRL, SL, SRA

Ces trois portes logiques sont utilisées pour le décalage de bits et sont plus complexes que les habituels AND, OR, XOR, etc. Pour que ces passerelles fonctionnent, nous devons d'abord retarder le signal d'horloge d'une durée appropriée afin de "décaler" les données.
Le deuxième argument passé à ces passerelles indique le nombre de bits à décaler.

Pour SL et SRL nous avons besoin

  1. Assurez-vous que les 12 bits les plus significatifs ne sont pas inclus (sinon la sortie sera 0), et
  2. Retardez les données pendant le temps souhaité en fonction des 4 bits les moins significatifs.
Cela peut être fait avec plusieurs passerelles AND/ANT et un multiplexeur.

SRA est légèrement différent car nous devons copier le bit de signe lors du décalage. Pour ce faire, nous effectuons une opération AND sur le signal d'horloge avec un bit de signe, puis nous copions la sortie plusieurs fois avec des séparateurs de fils et des portes OU.

Déclencheur Set-Reset (SR)

De nombreuses fonctions du processeur dépendent de la capacité à stocker des données. On peut l'implémenter avec deux globules rouges B12/S1. Les deux cellules peuvent rester allumées l'une l'autre ou elles peuvent être éteintes ensemble. Avec des circuits d'activation, de réinitialisation et de lecture supplémentaires, nous pouvons créer une simple bascule SR.

Synchroniseur

En convertissant les données série en parallèle, puis en activant plusieurs bascules SR, nous pouvons stocker un mot entier de données. Ensuite, pour récupérer à nouveau les données, nous pouvons simplement lire et réinitialiser tous les déclencheurs, et retarder les données en conséquence. Cela nous permettra de stocker un (ou plusieurs) mots de données pendant que nous en attendons un autre. Grâce à cela, nous pourrons synchroniser deux mots de données reçus à des instants différents.

Compteur de lecture

Cet appareil garde une trace du nombre de fois qu'il doit s'adresser à partir de la RAM. Il résout ce problème avec un dispositif similaire à la bascule SR : la bascule T. Chaque fois qu'une bascule en T reçoit une entrée, elle change d'état : si elle était activée, elle est désactivée, et vice versa. Lorsqu'une bascule en T change d'état, elle envoie une impulsion de sortie qui peut être transmise à une autre bascule en T, créant un compteur à deux bits.

Pour créer un compteur de lecture, nous devons mettre le compteur dans le mode d'adressage approprié à l'aide de deux passerelles ANT, et utiliser la sortie du compteur pour déterminer s'il faut envoyer le signal d'horloge à l'ALU ou à la RAM.

File d'attente de lecture

La file d'attente de lecture doit garder une trace du compteur de lecture qui a envoyé l'entrée à la RAM afin qu'elle puisse envoyer la sortie de la RAM au bon endroit. Pour ce faire, on utilise plusieurs bascules SR : une bascule pour chaque entrée. Lorsqu'un signal est transféré du compteur de lecture vers la RAM, le signal d'horloge est divisé et active la bascule SR du compteur. La broche RAM passe ensuite avec la bascule SR à travers la porte ET, et l'horloge RAM réinitialise la bascule SR.

ALU

L'ALU est similaire en fonctionnement à la file d'attente de lecture en ce sens qu'elle utilise également une bascule SR pour garder une trace de l'endroit où envoyer le signal. Tout d'abord, à l'aide du multiplexeur, la bascule SR du circuit logique correspondant à l'opcode d'instruction est activée. Ensuite, les valeurs des premier et deuxième arguments, ainsi que la bascule SR, passent par la porte ET, puis sont transférées aux chaînes logiques. Au passage, l'horloge réinitialise la bascule pour que l'ALU puisse être à nouveau utilisée.

RAM

La RAM était la partie la plus difficile de ce projet. Cela nécessitait un contrôle très spécifique de chaque bascule SR contenant des données. Pour la lecture, l'adresse est transférée au multiplexeur et transférée aux segments de RAM. Les segments de RAM sortent des données stockées en parallèle, qui sont sérialisées et sorties. Pour l'écriture, l'adresse est transférée à un autre multiplexeur, les données en cours d'écriture sont converties de la forme série à la forme parallèle et les segments de RAM propagent le signal à travers la RAM.

Le métapixel 22x22 de chaque segment RAM a la structure suivante :

En connectant toute la RAM, nous obtenons quelque chose comme ceci :

Mettre tous ensemble

Avec tous ces composants et l'architecture informatique générale décrite dans la partie 1, nous pouvons construire un ordinateur fonctionnel !

Partie 4 : QFTASM et Cogol

Présentation de l'architecture

En bref, notre ordinateur possède une architecture RISC Harvard asynchrone 16 bits. Lors de la construction d'un processeur à la main, une architecture RISC (Reduced Instruction Set Computer) est presque une exigence. Dans notre cas, cela signifie que le nombre d'opcodes est faible et, plus important encore, que toutes les instructions sont traitées de manière très similaire.

Pour référence, l'ordinateur Wireworld utilise une architecture déclenchée par le transport dans laquelle la seule instruction est MOV et les calculs sont effectués en écrivant/lisant des registres spéciaux. Bien que ce paradigme permette une architecture très facile à mettre en œuvre, le résultat est applicable à la limite : toutes les opérations arithmétiques/logiques/conditionnelles nécessitent Trois des instructions. Il était évident que nous voulions créer une architecture plus compréhensible.

Pour garder notre processeur simple tout en améliorant sa convivialité, nous avons pris plusieurs décisions de conception importantes :

  • Pas de registres. Chaque adresse dans la RAM est considérée comme égale et peut être utilisée comme argument dans n'importe quelle opération. Dans un sens, cela signifie que toute la RAM peut être considérée comme des registres. Cela signifie qu'il n'y a pas d'instructions spéciales de chargement/stockage.
  • Il en va de même pour l'allocation de mémoire. Tout ce qui peut être écrit ou lu a un schéma d'adressage unifié commun. Cela signifie que le compteur de programme (PC) a l'adresse 0 et que la seule différence entre les instructions normales et les instructions de contrôle est que les instructions de contrôle utilisent l'adresse 0.
  • Les données sont transmises en série et stockées en parallèle. En raison de la nature "électronique" de notre ordinateur, l'addition et la soustraction sont beaucoup plus faciles à mettre en œuvre lorsque les données sont transmises séquentiellement dans l'ordre little-endian (bit le moins significatif en premier). De plus, les données série permettent de s'affranchir des bus de données encombrants, très larges et peu pratiques pour une bonne gestion du temps (pour que les données soient ensemble, toutes les "bandes" du bus doivent avoir le même délai).
  • Architecture Harvard, c'est-à-dire qu'il existe une séparation entre la mémoire programme (ROM) et la mémoire de données (RAM). Bien que cela réduise la flexibilité du processeur, cela aide à optimiser la taille : la longueur du programme est beaucoup plus grande que la quantité de RAM dont nous avons besoin, nous pouvons donc scinder le programme en ROM et ensuite nous concentrer sur la compression ROM, ce qui est beaucoup plus facile à faire quand il est en "lecture seule".
  • Largeur de données de 16 bits. Il s'agit de la plus petite puissance de deux, qui est plus large que le champ Tetris standard (10 blocs). Cela nous donne une plage de données de -32768 à +32767 et une longueur de programme maximale de 65536 instructions. (2^8=256 instructions suffisent pour la plupart des choses simples qui peuvent être implémentées dans un processeur fictif, mais pas pour Tetris.)
  • conception asynchrone. Au lieu d'une horloge centrale (ou, de la même manière, de plusieurs horloges) réglant l'heure de l'ordinateur, toutes les données sont accompagnées d'un "signal d'horloge" qui se déplace en parallèle avec les données lorsqu'elles se déplacent dans l'ordinateur. Certains chemins peuvent être plus courts que d'autres, ce qui peut être difficile dans une conception d'horloge centrale, mais une conception asynchrone peut facilement gérer des opérations à temps variable.
  • Toutes les instructions sont de la même taille. Nous avons estimé qu'une architecture dans laquelle chaque instruction a 1 opcode avec trois opérandes (valeur, valeur, adresse cible) serait l'option la plus flexible. Ils incluent des opérations sur des données binaires ainsi que des sauts conditionnels.
  • Système simple de modes d'adressage. Avoir plusieurs modes d'adressage est très utile pour prendre en charge des éléments tels que les tableaux ou la récursivité. Nous avons pu implémenter plusieurs modes d'adressage importants à l'aide d'un système relativement simple.
Une illustration de notre architecture est fournie dans la partie 1.

Travaux et opérations d'ALU

Après cela, il a fallu décider quelles fonctions notre processeur devrait avoir. Une attention particulière doit être portée à la facilité de mise en œuvre et à la polyvalence de chaque commande.

Mouvements conditionnels

Les déplacements conditionnels sont très importants, ils servent au contrôle à petite et grande échelle. "Petite échelle" est la capacité de contrôler l'exécution d'un mouvement particulier de données, et "grande échelle" fait référence à son utilisation comme opération de saut conditionnel pour transférer le contrôle à n'importe quel morceau de code arbitraire. Le processeur ne opérations spéciales sauter car, en raison de l'allocation de mémoire, un déplacement conditionnel peut à la fois copier des données dans la RAM normale et copier l'adresse de destination dans le compteur de programme (PC). Nous avons également décidé d'abandonner les mouvements inconditionnels et les sauts inconditionnels pour une raison similaire : ces deux opérations peuvent être implémentées comme des mouvements conditionnels, dans lesquels la condition est toujours VRAIE.

Nous avons décidé d'utiliser deux types de mouvements conditionnels : "déplacer si non nul" (MNZ) et "déplacer si inférieur à zéro" (MLZ). Fonctionnellement, MNZ consiste à vérifier si un bit de données est 1, et MLZ consiste à vérifier si le bit de signe est 1. En conséquence, ils sont utiles pour les tests d'égalité et les comparaisons. Nous avons choisi ces deux mouvements car « déplacer si zéro » (MEZ) était censé produire un signal VRAI à partir d'un signal vide, et « déplacer si supérieur à zéro » (MGZ) est un test plus complexe nécessitant que le bit de signe soit égal à 0 et au moins un autre bit était 1.

Arithmétique

Les instructions suivantes les plus importantes pour décider de la conception du processeur étaient les opérations arithmétiques de base. Comme mentionné ci-dessus, nous utilisons des données sérielles little-endian, et le choix de endian a été déterminé par la facilité des opérations d'addition/soustraction. En obtenant d'abord le bit le moins significatif, les unités arithmétiques peuvent plus facilement suivre le bit de retenue.

Nous avons décidé d'utiliser la forme du complément à deux pour les nombres négatifs afin de rendre l'addition et la soustraction plus cohérentes. Il convient de noter que l'ordinateur Wireworld utilise un code inversé.

L'addition et la soustraction sont le lot du support arithmétique natif de notre processeur (à l'exception des décalages de bits, que nous verrons plus tard). D'autres opérations, comme la multiplication, sont trop complexes et ne peuvent pas être réalisées dans notre architecture, et doivent être implémentées dans un logiciel.

Opérations sur les bits

Comme vous pouvez le deviner, notre processeur a les instructions AND , OR et XOR. Au lieu de l'instruction NOT, nous avons décidé d'utiliser l'instruction "and-not" (ANT). La difficulté avec l'instruction NOT encore est qu'elle doit produire un signal en l'absence de signal, ce qui est difficile pour les automates cellulaires. L'instruction ANT renvoie 1 uniquement si le premier argument de bit est 1 et le premier argument de bit est 0. Autrement dit, NOT x est identique à ANT -1 x (et également XOR -1 x). De plus, ANT est plus polyvalent et présente un avantage majeur lors du masquage : dans le cas d'un programme Tetris, on s'en servira pour supprimer les tétrominos.

décalage de peu

Les opérations de décalage de bits sont les opérations les plus complexes gérées par une ALU. Ils reçoivent deux valeurs d'entrée : la valeur à décaler et la quantité à décaler. Malgré leur complexité (due à la valeur de décalage variable), ces opérations sont critiques pour de nombreuses tâches importantes, y compris les opérations "graphiques" utilisées dans Tetris. Les décalages de bits constituent également la base d'algorithmes de multiplication/division efficaces.

Notre processeur a trois opérations de décalage de bits - "décalage à gauche" (SL), "décalage logique à gauche" (SRL) et "décalage arithmétique à droite" (SRA). Les deux premiers décalages de bits (SL et SRL) remplissent les nouveaux bits avec des zéros (ce qui signifie qu'un nombre négatif décalé vers la droite ne sera plus négatif). Si le deuxième argument de décalage est en dehors de la plage de 0 à 15, alors, comme vous pouvez le deviner, le résultat sera tous des zéros. Pour le dernier décalage de bit, SRA , le décalage de bit préserve le signe de l'entrée, et agit donc comme une vraie division par deux.

Pipeline d'instructions

Il est temps de parler de quelques détails d'architecture de base. Chaque cycle CPU se compose des cinq étapes suivantes :

1. Obtenir l'instruction actuelle de la ROM

La valeur actuelle de PC est utilisée pour obtenir l'instruction correspondante de la ROM. Chaque instruction a un opcode et trois opérandes. Chaque opérande se compose d'un mot de données et d'un mode d'adressage. Ces parties sont séparées les unes des autres lorsqu'elles sont lues à partir de la ROM.

L'opcode est de 4 bits afin de pouvoir supporter 16 opcodes uniques, dont 11 sont attribués :

0000 MNZ Déplacer si pas zéro
0001 Déplacement MLZ si inférieur à zéro
0010 AJOUT
0011 SOUS SOUStraction
0100 ET ET au niveau du bit
0101 OU OU au niveau du bit
0110 XOR OR exclusif au niveau du bit
0111 ANT bitwise And-Not
1000 SL Décalage à gauche
1001 SRL Maj Logique Gauche
1010 SRA Shift droite arithmétique
1011 non attribué
1100 non attribué
1101 non attribué
1110 non attribué
1111 non attribué

2. Enregistrement du résultat (si nécessaire) précédent instructions dans la RAM

L'exécution de l'écriture dépend de l'état de l'instruction précédente (par exemple, de la valeur du premier argument du coup conditionnel). L'adresse d'écriture est déterminée par le troisième opérande de l'instruction précédente.

Il est important de noter que l'écriture est effectuée après réception de l'instruction. Cela se traduit par la création d'un créneau de retard de branchement, dans lequel l'instruction est exécutée immédiatement après l'instruction de branchement (toute opération qui écrit sur le PC) au lieu de la première instruction de l'adresse de destination de branchement.

Dans certains cas (par exemple, avec des sauts inconditionnels), le créneau de retard de saut peut être éliminé par optimisation. Dans d'autres cas, ce n'est pas possible et l'instruction après la branche doit être laissée vide. De plus, ce type de créneau de retard doit utiliser une adresse cible de branchement qui est inférieure d'une adresse à l'instruction cible elle-même pour tenir compte de l'incrément PC en cours d'exécution.

En bref, étant donné que la sortie de l'instruction précédente est écrite dans la RAM après la réception de l'instruction suivante, les sauts conditionnels doivent être suivis d'une instruction vide. Sinon, le PC ne se mettra pas à jour pour migrer correctement.

3. Lecture des données pour les arguments de l'instruction en cours à partir de la RAM

Comme mentionné ci-dessus, chacun des trois opérandes se compose à la fois d'un mot de données et d'un mode d'adressage. Le mot de données est de 16 bits, la même capacité que la RAM. Le mode d'adressage prend 2 bits.

Les modes d'adressage peuvent être une source de complexité importante pour de tels processeurs car de nombreux modes d'adressage du monde réel nécessitent des calculs en plusieurs étapes (par exemple, l'ajout de décalages). Dans le même temps, les modes d'adressage flexibles jouent un rôle important dans la convivialité du processeur.

Nous avons cherché à unifier les concepts d'utilisation de nombres codés en dur comme opérandes et d'utilisation d'adresses de données comme opérandes. Cela a conduit à la création de modes d'adressage basés sur des compteurs : le mode d'adressage d'un opérande est simplement un nombre spécifiant combien de fois les données doivent être transférées dans un cycle de lecture RAM. Ceux-ci incluent l'adressage direct, direct, indirect et double indirect.

00 immédiat : valeur codée en dur. (pas de lecture depuis la RAM)
01 direct : lit les données à partir de cette adresse RAM. (une lecture depuis la RAM)
10 indirect : lit les données à partir de l'adresse spécifiée dans cette adresse. (deux lectures de la RAM)
11 double indirect : lit les données à partir de l'adresse spécifiée dans l'adresse spécifiée par cette adresse. (trois lectures de la RAM)

Après décodage de la référence, les trois opérandes de l'instruction se voient attribuer des rôles différents. Le premier opérande est généralement le premier argument d'un opérateur binaire, mais sert également de condition lorsque l'instruction en cours est un mouvement conditionnel. Le deuxième opérande sert de deuxième argument à l'opérateur binaire. La troisième instruction sert d'adresse de destination pour le résultat de l'instruction.

Comme les deux premières instructions servent de données et la troisième d'adresse, les modes d'adressage ont des interprétations légèrement différentes selon la position dans laquelle ils sont utilisés. Par exemple, le mode direct est utilisé pour lire des données à partir d'une adresse RAM fixe (car une lecture RAM est requise), mais le mode immédiat est utilisé pour écrire des données sur une adresse RAM fixe (car aucune lecture RAM n'est requise).

4. Calculer le résultat

L'opcode et ses deux premiers opérandes sont envoyés à l'ALU pour effectuer l'opération binaire. Pour les opérations arithmétiques, de bit et de décalage, cela signifie que l'opération correspondante est effectuée. Pour les mouvements conditionnels, cela signifie simplement renvoyer le deuxième opérande.

L'opcode et le premier opérande sont utilisés pour évaluer une condition qui détermine si le résultat doit être écrit en mémoire. Dans le cas de mouvements conditionnels, cela signifie que vous devez soit déterminer si l'un des bits d'opérande est égal à 1 (pour MNZ), soit vous devez déterminer si le bit de signe est égal à 1 (pour MLZ). Si l'opcode n'est pas un mouvement conditionnel, alors l'écriture est toujours effectuée (la condition est toujours vraie).

5. Incrément du compteur de programme

Puis, enfin, la valeur du compteur de programme est lue, incrémentée et écrite.

Parce que l'incrément PC est situé entre l'instruction lue et l'instruction écriture, une instruction qui incrémente PC de 1 est une non-op. Une instruction qui copie le PC sur lui-même provoque l'exécution de l'instruction suivante deux fois de suite. Mais il ne faut pas oublier que si vous ne faites pas attention au pipeline d'instructions, plusieurs instructions PC consécutives peuvent entraîner des effets complexes, notamment une boucle sans fin.

Odyssey va créer un assembleur pour "Tetris"

Nous avons créé pour notre processeur nouveau langage assembleur QFTASM. Ce langage d'assemblage correspond un à un au code machine dans la ROM de l'ordinateur.

Tout programme QFTASM est écrit sous la forme d'une série d'instructions ligne par ligne. Chaque ligne est formatée comme ceci :

[numéro de ligne] [opcode] [arg1] [arg2] [arg3] ; [commentaire facultatif]

Liste des opcodes

Comme mentionné ci-dessus, onze opcodes sont pris en charge par l'ordinateur, chacun ayant trois opérandes :

MNZ [test] [valeur] [destination] - déplacer si différent de zéro ; définit [destination] sur [valeur] si [vérifier] est différent de zéro.
MLZ [vérifier] [valeur] [destination] - déplacer si inférieur à zéro ; définit [destination] sur [valeur] si [vérifier] n'est pas inférieur à zéro.
ADD [valeur1] [valeur2] [adresse de destination] – addition ; stocke [valeur1] + [valeur2] dans [destination].
SUB [valeur1] [valeur2] [adresse de destination] – soustraction ; stocke [valeur1] - [valeur2] dans [destination].
ET [valeur1] [valeur2] [adresse de destination] – ET au niveau du bit ; stocke [valeur1] et [valeur] dans [destination].
OU [valeur1] [valeur2] [adresse de destination] – OU au niveau du bit ; enregistre [valeur1] | [valeur2] dans [destination].
XOR [valeur1] [valeur2] [adresse de destination] – XOR au niveau du bit ; stocke [valeur1] ^ [valeur2] dans [destination].
ANT [valeur1] [valeur2] [adresse de destination] – NAND au niveau du bit ; stocke [value1] & (![value2]) dans [destination].
SL [valeur1] [valeur2] [adresse de destination] – décalage vers la gauche ; enregistre [valeur1]<< [значение2] в [адресе назначения].
SRL [valeur1] [valeur2] [adresse de destination] – décalage logique vers la droite ; stocke [valeur1] >>> [valeur2] dans [destination]. Ne conserve pas le signe.
SRA [valeur1] [valeur2] [adresse de destination] – décalage arithmétique vers la droite ; stocke [valeur1] >> [valeur2] dans [destination] avec le signe conservé.

Modes d'adressage

Chaque opérande contient à la fois une valeur de données et un mode d'adressage. La valeur de données est décrite par un nombre décimal compris entre -32768 et 65536. Le mode d'adressage est décrit par un préfixe d'une lettre à la valeur de données.

Préfixe du nom du mode
0 immédiat (non)
1 A droit
2 indirects B
3 do doubles indirects

Exemple de code

Nombres de Fibonacci en cinq lignes :

0.MLZ -1 1 1; valeur initiale
1. MLZ-1 A2 3 ; démarrage du cycle, décalage des données
2. MLZ-1 A1 2; décalage de données
3. MLZ-1 0 0 ; fin de cycle
4. AJOUTER A2 A3 1 ; créneau de retard de branche, calcul du terme suivant

Ce code calcule une série de nombres de Fibonacci, l'adresse RAM 1 contient le membre courant. Après 28657 ça déborde vite.

Code gris :

0.MLZ-1 5 1; valeur initiale de l'adresse RAM pour l'écriture
1. SOUS A1 5 2 ; le début de la boucle, déterminant le nombre binaire à convertir en code Gray
2. SRL A2 1 3 ; décaler de 1 vers la droite
3. XOR A2 A3 A1 ; XOR et stocker le code gris à destination
4. SOUS B1 42 4 ; prenez le code gris et soustrayez 42 (101010)
5. MNZ A4 0 0 ; si le résultat n'est pas nul (code Gray != 101010), répéter la boucle
6. AJOUTER A1 1 1 ; emplacement de retard de branche, incrément d'adresse de destination

Ce programme calcule le code Gray et stocke le code dans des adresses consécutives à partir de l'adresse 5. Le programme utilise plusieurs fonctionnalités utiles, comme l'adressage indirect et le branchement conditionnel. Il ne s'arrête que lorsque le code Gray résultant est 101010 , ce qui se produit lorsque vous entrez 51 à l'adresse 56.

Interprète en ligne

El "endia Starman a créé un interpréteur en ligne très utile. Dans celui-ci, vous pouvez parcourir le code, définir des points d'arrêt, écrire manuellement dans la RAM et visualiser l'état de la RAM à l'écran.

Cogol

Après avoir choisi l'architecture et le langage d'assemblage, la prochaine étape du côté "logiciel" du projet consiste à créer un langage de haut niveau adapté à "Tetris". C'est pourquoi j'ai créé Cogol. Le nom est à la fois un jeu de mots sur "COBOL" et un acronyme pour "C of Game of Life", bien qu'il soit intéressant de noter que Cogol est à C ce que notre ordinateur est à la réalité.

Cogol existe juste un niveau au-dessus du langage d'assemblage. En général, la plupart des lignes de programme Cogol correspondent aux lignes du langage assembleur, mais le langage a plusieurs caractéristiques importantes :

  • Les fonctionnalités clés incluent des variables nommées avec affectation et des opérateurs avec une syntaxe plus lisible. Par exemple, ADD A1 A2 3 devient z = x + y ; . Le compilateur lie les variables aux adresses.
  • Constructions de boucle telles que if()() , while()() et do()while(); permettre au compilateur de gérer les branchements.
  • Tableaux unidimensionnels (avec arithmétique de pointeur) utilisés pour le champ Tetris.
  • Sous-programmes et pile d'appels. Ils sont utilisés pour éviter la duplication d'extraits de code volumineux et pour prendre en charge la récursivité.
Le compilateur (que j'ai écrit à partir de zéro) est très simple/naïf, mais j'ai essayé d'optimiser manuellement certaines des constructions de langage pour réaliser des programmes compilés courts.

Voici un bref aperçu du fonctionnement des différentes fonctionnalités du langage :

Tokénisation

Le code source est segmenté linéairement (en une seule passe) sur la base de règles simples sur les caractères qui peuvent coexister dans le jeton. Lorsqu'un caractère est rencontré qui ne peut pas être adjacent au dernier caractère du jeton actuel, le jeton actuel est considéré comme complet et le nouveau personnage commence un nouveau jeton. Certains caractères (par exemple, ( ou,) ne peuvent pas coexister avec d'autres, ils sont donc eux-mêmes des jetons distincts. D'autres (par exemple, > ou =) ne peuvent coexister qu'avec eux-mêmes, c'est-à-dire qu'ils peuvent créer des jetons tels que >>> ou == Les caractères d'espacement forcent les limites des jetons, mais ne sont pas inclus dans le résultat Le caractère le plus difficile à marquer est - , car il peut représenter à la fois la soustraction et la négation unaire, et nécessite donc un traitement spécial.

Analyse

L'analyse se fait également en une seule passe. Le compilateur a des méthodes pour traiter chacune des constructions de langage, et après avoir été passés à diverses méthodes de compilateur, les jetons sont extraits de la liste globale des jetons. Si le compilateur rencontre un jeton inattendu, il génère une erreur de syntaxe.

Allocation globale de mémoire

Le compilateur affecte à chaque variable globale (mot ou tableau) sa ou ses adresse(s) propre(s) en RAM. Toutes les variables doivent être déclarées avec le mot clé my afin que le compilateur sache leur allouer de l'espace. La gestion de la mémoire d'adresses temporaires est beaucoup plus cool que les variables globales nommées. De nombreuses instructions (notamment les instructions conditionnelles et de nombreux accès aux tableaux) nécessitent des adresses "temporaires" pour stocker les calculs intermédiaires. Lors de la compilation, le compilateur alloue et libère des adresses temporaires selon les besoins. Si le compilateur a besoin de plus d'adresses temporaires, il leur allouera plus de RAM. Je suppose que les programmes n'utilisent généralement que quelques adresses temporaires, chaque adresse étant utilisée plusieurs fois ...

Constructions IF-ELSE

Les constructions If-else ont une syntaxe C standard :

Autre code
si (cond) (
premier corps
) autre (
deuxième corps
}
autre code

Une fois converti en QFTASM, le code obtient la structure suivante :

Autre code
vérification de l'état
saut conditionnel
premier corps
sauter sans condition
deuxième corps (lieu de saut conditionnel)
un autre code (lieu de saut inconditionnel)

Si le premier corps est exécuté, le second est sauté. Si le premier corps est ignoré, le second est exécuté.

En assembleur, un "test de condition" est généralement une simple soustraction, et le signe du résultat détermine si une branche doit être prise ou si le corps doit être exécuté. Pour gérer les inégalités comme > ou<= используется инструкция MLZ . Инструкция MNZ используется для обработки == , потому что она выполняет переход через тело, когда разность не равна нулю (то есть когда аргументы неравны). Условия с несколькими выражениями пока не поддерживаются.

S'il n'y a pas de construction else, le saut inconditionnel est également omis et le code QFTASM ressemble à ceci :

Autre code
vérification de l'état
saut conditionnel
corps
autre code (emplacement de saut conditionnel)

WHILE construit

Alors que les constructions ont également une syntaxe C standard :

Autre code
tandis que (état) (
corps
}
autre code

Une fois converti en QFTASM, le code a le schéma suivant :

Autre code
sauter sans condition
corps (emplacement de la branche conditionnelle)
vérification de l'état (emplacement du saut inconditionnel)
saut conditionnel
autre code

Le test de condition et le branchement conditionnel sont à la fin du bloc, ce qui signifie qu'ils sont ré-exécutés après chaque exécution du bloc. Lorsque la condition renvoie false, le corps n'est pas exécuté et la boucle se termine. Lorsque la boucle commence à s'exécuter, le flux de contrôle saute à travers le corps de la boucle jusqu'au code de condition, donc si la condition est fausse la première fois, le corps n'est jamais exécuté.

L'instruction MLZ permet de gérer les inégalités de la forme > ou<= . В отличие от выполнения конструкций if , инструкция MNZ используется для обработки!= , потому что она переходит к телу, когда разность не равна нулю (то есть когда аргументы неравны).

Constructions DO-WHILE

La seule différence entre while et do-while est que le corps de la boucle do-while n'est pas contourné la première fois, donc elle s'exécute toujours au moins une fois. J'utilise généralement des constructions do-while pour enregistrer quelques lignes de code d'assemblage lorsque je sais avec certitude que la boucle ne devra jamais être complètement ignorée.

Tableaux

Les tableaux unidimensionnels sont implémentés sous forme de blocs de mémoire contigus. Tous les tableaux ont une longueur fixe en fonction de la déclaration. Les tableaux sont déclarés comme ceci :

Mon alpha ; # tableau vide
mon bêta = (3,2,7,8); # les quatre premiers éléments sont pré-écrits avec ces valeurs

Voici une allocation de RAM possible pour la baie, montrant que les adresses 15-18 lui sont réservées :

15 : alpha
16 : Alpha
17 : alpha
18 : alpha

Les adresses marquées avec alpha sont remplies avec un pointeur vers l'emplacement de alpha , de sorte que l'adresse 15 contient dans ce cas la valeur 16. La variable alpha peut être utilisée comme pointeur de pile dans le code Cogol si le tableau doit être utilisé comme pile .

Les éléments de tableau sont accessibles à l'aide de la notation standard array . Si la valeur de index est une constante, cette référence est automatiquement renseignée avec l'adresse absolue de l'élément. Sinon, il effectue une arithmétique de pointeur (juste une addition) pour trouver l'adresse absolue souhaitée. L'indexation en ligne est également possible, comme alpha .

Sous-programmes et appels

Les sous-programmes sont des blocs de code qui peuvent être appelés depuis différents contextes, ils permettent d'éviter la duplication de code et de créer des programmes récursifs. Voici un exemple de programme avec une routine récursive pour générer des nombres de Fibonacci (l'algorithme le plus lent) :

# calculer récursivement le dixième nombre de Fibonacci
appel display = fib(10).sum;
sous fib(cur,sum) (
si (cur<= 2) {
somme = 1 ;
revenir;
}
cur-- ;
somme des appels = fib(cur).sum;
cur-- ;
somme des appels += fib(cur).sum;
}

Un sous-programme est déclaré avec le mot clé sub et peut être placé n'importe où dans le programme. Chaque sous-programme peut avoir plusieurs variables locales, chacune étant déclarée dans sa liste d'arguments. Ces arguments reçoivent également des valeurs par défaut.

Pour gérer les appels récursifs, les variables locales d'un sous-programme sont stockées sur la pile. La dernière variable statique dans la RAM est le pointeur de pile d'appels, et toute la mémoire qui suit sert de pile d'appels. Lorsqu'un sous-programme est appelé, il crée un nouveau cadre sur la pile des appels, qui inclut toutes les variables locales et l'adresse de retour (ROM). Chaque sous-programme du programme reçoit une adresse RAM statique, qui sert de pointeur. Ce pointeur spécifie l'emplacement de l'appel de sous-programme "courant" sur la pile des appels. Le référencement d'une variable locale se fait en utilisant la valeur de ce pointeur statique plus un décalage pour donner l'adresse de cette variable locale particulière. La pile des appels contient également la valeur précédente du pointeur statique. Voici la distribution des variables pour la RAM statique et la trame d'appel de sous-programme pour le programme ci-dessus :

Carte RAM :
0 :pc
1 : affichage
2 : gratter0
3 : mensonge
4 : gratter1
5 : scratch2
6 : gratter3
7 : appeler

fibmap :
0 : retour
1 : appel_précédent
2:cur
3 : somme

Un aspect intéressant des sous-programmes est qu'ils ne renvoient aucune valeur spécifique. Après l'exécution d'un sous-programme, toutes ses variables locales peuvent être lues, de sorte qu'un grand nombre de données peuvent être récupérées à partir d'un appel de sous-programme. Ceci est implémenté en stockant un pointeur vers cet appel de sous-programme particulier, qui peut ensuite être utilisé pour restaurer toutes les variables locales à partir du cadre de pile (récemment libéré).

Un sous-programme peut être appelé de plusieurs manières, qui utilisent toutes le mot-clé call :

Callfib(10); # le sous-programme est exécuté, aucune valeur de retour n'est stockée

pointeur d'appel = fib(10); # exécute le sous-programme et renvoie le pointeur
display = pointer.sum; # accéder à une variable locale et l'affecter à une variable globale

appel display = fib(10).sum; # stocker la valeur de retour immédiatement

appel display += fib(10).sum; # vous pouvez également utiliser d'autres types d'opérateurs d'affectation avec la valeur de retour

Pour appeler un sous-programme, vous pouvez spécifier n'importe quel nombre de valeurs comme arguments. Tous les arguments non spécifiés seront remplis avec leurs valeurs par défaut (le cas échéant). Si l'argument n'est pas spécifié et n'a pas de valeur par défaut effacée (pour économiser des instructions/du temps), il peut prendre n'importe quelle valeur au début de la sous-routine.

Les pointeurs sont un moyen d'accéder à plusieurs variables locales d'un sous-programme, mais il est important de noter que ce pointeur n'est pas seulement temporaire : si un autre appel au sous-programme est effectué, les données pointées par le pointeur seront détruites.

Balises de débogage

Tout bloc (...) dans un programme Cogol peut être précédé d'une étiquette descriptive de plusieurs mots. Cette marque est attachée au code assembleur compilé sous forme de commentaire et peut être très utile pour le débogage car elle facilite la recherche des bons morceaux de code.

Optimisation des créneaux de retard de branche

Pour améliorer la vitesse du code compilé, le compilateur Cogol effectue une optimisation très simple de l'emplacement du délai de branchement en dernier passage dans le code QFTASM. Pour toute branche inconditionnelle avec un créneau de retard de branche vide, le créneau de retard peut être rempli avec la première adresse de branche d'instruction, et l'adresse de branche est incrémentée pour pointer vers l'instruction suivante. Cela permet généralement d'économiser un cycle à chaque fois qu'un branchement inconditionnel est exécuté.

Coder Tetris avec Cogol

Le programme Tetris fini a été écrit en Cogol et son code source est disponible. Le code QFTASM compilé est disponible. Pour plus de commodité, le lien permanent est répertorié ici : Tetris dans QFTASM. Étant donné que notre objectif était de produire du code assembleur (et non du code Cogol), le code Cogol résultant est plutôt difficile à manier. De nombreuses parties du programme doivent être placées dans des sous-programmes, mais ces sous-programmes sont en fait si courts que la duplication de code enregistre plus d'instructions que de constructions d'appel. Le code fini ne contient qu'un seul sous-programme en plus du code principal. De plus, de nombreux tableaux ont été supprimés et remplacés soit par une liste de variables individuelles de même longueur, soit par un ensemble de nombres codés en dur dans le programme. Le code QFTASM compilé fini contient moins de 300 instructions, bien qu'il soit légèrement plus long que la source Cogol elle-même.

Partie 5 : assemblage, diffusion et avenir

Une fois que nous avons le programme assembleur du compilateur, nous pouvons commencer à assembler la ROM pour l'ordinateur Varlife et à tout traduire en un grand modèle Game of Life !

Assemblée

L'assemblage d'un programme d'assemblage en ROM se fait un peu comme dans la programmation traditionnelle : chaque instruction est traduite en un équivalent binaire, puis elles sont toutes concaténées en un seul grand objet binaire appelé fichier exécutable. Pour nous, la seule différence est que le blob doit être diffusé sur la chaîne et connecté à l'ordinateur.

L'avenir du projet

Nous avons donc créé Tetris, et c'est tout, non ? Rien de tel. Nous avons d'autres objectifs pour ce projet sur lequel nous travaillons :
  • muddyfish et Kritixi Lithos continuent de travailler sur un langage de haut niveau qui se compile en QFTASM.
  • El "endia Starman travaille sur les mises à jour de l'interprète en ligne QFTASM.
  • quartata travaille sur un backend GCC qui permettra à GCC de compiler du code C et C++ indépendant (et éventuellement d'autres langages comme Fortran, D ou Objective-C) dans QFTASM. Cela vous permettra d'écrire des programmes plus complexes dans un langage plus familier, mais sans bibliothèque standard.
  • L'un des plus grands obstacles que nous devons surmonter pour aller de l'avant est que nos outils ne peuvent pas créer de code indépendant de la position (PIC) (c'est-à-dire des sauts relatifs). Sans PIC, nous ne pouvons pas utiliser de liens, c'est-à-dire que nous ne pouvons pas tirer parti de la liaison avec des bibliothèques prêtes à l'emploi. Nous travaillons à trouver un moyen de mettre en œuvre correctement le PIC.
  • Nous réfléchissons au prochain programme à écrire pour l'ordinateur QFT. Jusqu'à présent, Pong semble être une bonne cible pour nous.

Partie 6 : nouveau compilateur pour QFTASM

Bien que le langage Cogol soit une implémentation assez rudimentaire de Tetris, il est trop simple et de bas niveau pour une programmation à usage général à un niveau bien lu.

Nous avons commencé à travailler sur le nouveau langage en septembre 2016. Le processus de développement du langage a été lent en raison d'erreurs difficiles à comprendre, comme dans la vraie vie.

Nous avons créé un langage de bas niveau avec une syntaxe similaire à Python, comprenant un système de type simple, des sous-programmes récursifs et des opérateurs d'intégration.

Le compilateur de texte dans QFTASM a été créé en quatre étapes : tokenizer, arbre de grammaire, compilateur de haut niveau et compilateur de bas niveau.

Générateur de jetons

Le développement de Python a commencé en utilisant la bibliothèque intégrée de tokenizer, donc cette étape était assez simple.

Seules des modifications mineures à la sortie par défaut devaient être apportées, y compris la suppression des commentaires (mais pas #includes).

Arbre de grammaire

L'arbre de grammaire a été créé dans l'espoir d'une extensibilité pratique sans qu'il soit nécessaire de modifier le code source.

La structure de l'arborescence est stockée dans un fichier XML qui contient la structure des nœuds qui composent l'arborescence et leurs connexions aux autres nœuds et jetons.

La grammaire devait prendre en charge les nœuds répétés ainsi que les nœuds facultatifs. Nous avons résolu ce problème en ajoutant des balises méta qui décrivent la façon dont les jetons sont lus.

Les jetons générés sont ensuite analysés par les règles de grammaire de sorte que la sortie forme un arbre d'éléments de grammaire, tels que sub et generic_variables , qui à leur tour contiennent d'autres éléments et jetons de grammaire.

Compilation en code de haut niveau

Chaque fonction de langage doit être compilée dans des constructions de haut niveau. Par exemple assign(a, 12) et call_subroutine(is_prime, call_variable=12, return_variable=temp_var) . Ce segment exécute des fonctions telles que l'incorporation d'éléments. Ils sont définis comme un opérateur , et leur particularité est qu'ils sont intégrés à chaque fois qu'un opérateur tel que + ou % est utilisé. Par conséquent, ils sont plus limités que le code normal - ils ne peuvent pas utiliser leur propre opérateur et tout autre opérateur qui dépend de celui défini.

Lors de l'inlining, les variables internes sont remplacées par celles qui ont été appelées. Ainsi c'est :

Opérateur(int a + int b) -> int c
retourner __AJOUTER__(a, b)
entier je = 3+3

Se transforme en

Int je = __AJOUTER__(3, 3)

Cependant, ce comportement peut être malveillant et sujet aux erreurs si les variables d'entrée et de sortie pointent vers le même emplacement mémoire. Pour utiliser un comportement plus "sûr", le mot-clé unsafe régule le processus de compilation afin que ces variables supplémentaires soient créées et copiées à partir de la substitution selon les besoins.

Variables temporaires (variable scratch) et opérations complexes

Les opérations mathématiques telles que a += (b + c) * 4 ne peuvent pas être calculées sans utiliser des cellules de mémoire supplémentaires. Le compilateur de haut niveau gère ce problème en séparant les opérations en différentes parties :

Scratch_1=b+c
scratch_1 = scratch_1 * 4
un = un + scratch_1

Cela introduit le concept de variables temporaires utilisées pour stocker des informations intermédiaires de calculs. Ils sont attribués en cas de besoin et libérés après achèvement des travaux dans la piscine commune. Cela réduit le nombre de zones de mémoire temporaire nécessaires au fonctionnement. Les variables temporaires sont considérées comme globales.

Chaque sous-programme a son propre VariableStore pour stocker les références à toutes les variables utilisées par le sous-programme et leurs types. A la fin de la compilation, ils sont traduits en décalages relatifs depuis le début du magasin, puis on leur attribue des adresses valides en RAM.

Structure de la RAM

Compteur de commandes
Variables locales de sous-programme
Variables locales d'instruction (réutilisées)
Variables temporaires
Variable de résultat
pointeur de pile
Empiler
...

Compilation de bas niveau

Les seules choses avec lesquelles un compilateur de bas niveau doit travailler sont sub , call_sub , return , assign , if et while . Il s'agit d'une liste de tâches considérablement réduite, ce qui est plus pratique à traduire en instructions QFTASM.

sous

Il spécifie le début et la fin d'un sous-programme nommé. Le compilateur de bas niveau ajoute des étiquettes et, dans le cas de la routine principale, ajoute une instruction de sortie (saut à la fin de la ROM).

si et pendant

Les interpréteurs while et if de bas niveau sont assez simples : ils reçoivent des pointeurs vers leurs conditions et la transition qui en dépend. tandis que les boucles sont légèrement différentes en ce sens qu'elles sont compilées comme

...
condition
aller vérifier
le code
condition
si condition : sauter au code
...

call_sub et retour

Contrairement à la plupart des architectures, la machine pour laquelle nous compilons n'a pas de support matériel pour ajouter et faire éclater une pile. Cela signifie que l'ajout et le retrait de la pile prennent deux instructions chacun. Dans le cas de la récupération, nous décrémentons le pointeur de pile et copions la valeur à l'adresse. Dans le cas d'ajout, nous copions la valeur de l'adresse à l'adresse du pointeur de pile actuel, puis incrémentons.

Toutes les variables locales d'un sous-programme sont stockées dans un emplacement fixe de la RAM défini au moment de la compilation. Pour implémenter la récursivité, toutes les variables locales d'une fonction sont poussées sur la pile au début de l'appel. Les arguments du sous-programme sont ensuite copiés à leur position dans le magasin de variables locales. La valeur de l'adresse de retour est poussée sur la pile et le sous-programme est exécuté.

Lorsqu'une construction de retour est rencontrée, le haut de la pile est dépilé et le compteur de programme est défini sur cette valeur. Les valeurs des variables locales de la routine appelante sont extraites du haut de la pile et renvoyées à leur position précédente.

attribuer

L'affectation de variable est la plus simple à compiler : vous devez prendre la variable et la valeur et les compiler sur une seule ligne : MLZ -1 VALUE VARIABLE

Attribution d'adresse de saut

Enfin, le compilateur génère des adresses de saut pour les étiquettes ajoutées aux instructions. La position absolue des étiquettes est déterminée, après quoi les références à ces étiquettes sont remplacées par ces valeurs. Les étiquettes elles-mêmes sont supprimées du code, après quoi, enfin, des numéros d'instruction sont ajoutés au code compilé.

Exemple de compilation pas à pas

Nous avons parcouru toutes les étapes, passons maintenant au processus de compilation d'un vrai programme étape par étape.

#include stdint

principal sous
entier a = 8
entier b = 12
entier c = a*b

Super, c'est assez simple. Évidemment, à la fin du programme a = 8 , b = 12 , c = 96 . Tout d'abord, collons les parties pertinentes de stdint.txt :

Opérateur (int a + int b) -> int
retourner __AJOUTER__(a, b)

Opérateur (int a - int b) -> int
retourner __SUB__(a, b)

Opérateur(int a< int b) ->bourdonner
booléen rtn = 0
rtn = __MLZ__(a-b, 1)
retour rtn

Opérateur non sécurisé (int a * int b) -> int
entier rtn = 0
pour (int je = 0; je< b; i+=1)
rtn += un
retour rtn

principal sous
entier a = 8
entier b = 12
entier c = a*b

Du coup, les choses se sont un peu compliquées. Passons au tokenizer et voyons ce qui se passe. A ce stade, nous n'avons qu'un flux linéaire de jetons sans aucune structure

Opérateur NOM
OP LPAR (
NOM NOM int
NOM NOM a
PLUS OP+
NOM NOM int
NOM NOM b
RPAR OP)
OP OP ->
NOM NOM int
NOUVELLE LIGNE NOUVELLE LIGNE
RETRAIT RETRAIT
NOM retour
NOM NOM __AJOUTER__
OP LPAR (
NOM NOM a
COMMAOP,
NOM NOM b
RPAR OP)
...

Maintenant, tous les jetons passeront par l'analyseur de grammaire, qui produira un arbre avec le nom de chacune des parties. Il démontre la structure de haut niveau du code lu.

Fichier GrammarTree
"stmts": , int op(*:rtn))
("call_sub", "__ADD__", , int op(*:i))
("attribuer", booléen global scratch_2, 0)
("call_sub", "__SUB__", , global int scratch_3)
("call_sub", "__MLZ__", , booléen global scratch_2)
("while", "end", 1, global bool scratch_2)
("assigner", int main_c, int op(*:rtn))
("sous", "fin", "principal")

Le compilateur de bas niveau doit ensuite convertir cette vue de haut niveau en code QFTASM. Les variables se voient attribuer une place dans la RAM comme suit :

int program_counter
int op(*:i)
int main_a
int op(*:rtn)
int main_c
int main_b
entier global scratch_1
global booléen scratch_2
entier global scratch_3
entier global scratch_4
entier global
entier global

Les instructions simples sont ensuite compilées. Enfin, les numéros d'instruction sont ajoutés et le résultat est le code exécutable QFTASM.

0.MLZ 0 0 0;
1. MLZ-1 12 11 ;
2. MLZ-1 8 2;
3. MLZ-1 12 5 ;
4. MLZ-1 0 3 ;
5. MLZ-1 0 1 ;
6. MLZ-1 0 7;
7. SUB A1 A5 8 ;
8. MLZ A8 1 7;
9. MLZ-1 15 0 ;
10. MLZ 0 0 0 ;
11. AJOUTER A3 A2 3 ;
12. AJOUTER A1 1 1 ;
13. MLZ-1 0 7;
14. SUB A1 A5 8 ;
15. MLZ A8 1 7;
16. MNZ A7 10 0;
17. MLZ 0 0 0 ;
18. MLZ-1 A3 4 ;
19. MLZ-1-2 0;
20. MLZ 0 0 0 ;

Syntaxe

Nous avons donc un langage simple et nous devons y écrire un petit programme. Nous utilisons l'indentation comme en Python, en séparant les blocs logiques et le flux de commandes. Cela signifie que les espaces sont importants dans nos programmes. Chaque programme terminé a un sous-programme principal qui agit comme la fonction main() dans les langages de type C. La fonction est exécutée au début du programme.

Variables et types

Lorsqu'une variable est définie pour la première fois, elle a besoin d'un type qui lui est associé. Jusqu'à présent, nous avons défini les types int et bool, avec une syntaxe définie pour les tableaux, mais pas pour le compilateur.

Bibliothèques et opérateurs

Il existe une bibliothèque stdint.txt qui définit les principaux opérateurs. S'il n'est pas intégré au programme, même les instructions les plus simples ne seront pas définies. Vous pouvez utiliser cette bibliothèque avec #include stdint . stdint définit des opérateurs tels que + , >> et même * avec % , dont aucun n'a d'opcode QFTASM direct.

De plus, le langage permet l'invocation directe des opcodes QFTASM en utilisant __OPCODENAME__ .

En stdint, l'addition est définie comme suit

Opérateur (int a + int b) -> int
retourner __AJOUTER__(a, b)

Cette notation définit ce que l'opérateur + doit faire lorsqu'on lui donne deux entiers.

Mots clés:

  • tetris
  • vie de jeu
  • automates cellulaires
  • le jeu de la vie de conway
Ajouter des balises

Les compétitions du jeu "Tetris-online" se déroulent selon les règles suivantes.

1. Chaque participant s'inscrit sur le site du jeu sous un nom de jeu spécifique. Les noms des participants ne sont pas répétés.

2. Le championnat se déroule pendant un certain temps. À tout moment de cette période, tout participant inscrit peut se rendre sur le site Web du championnat et commencer le jeu test. A la fin du jeu, le résultat

(nombre de points marqués) est enregistré et consigné dans le protocole.

3. Les participants ont le droit de jouer plusieurs fois. Le nombre de tentatives par participant n'est pas limité.

4. Le résultat final du participant est déterminé par un jeu, le meilleur pour ce participant.

5. Une place plus élevée dans la compétition est occupée par le participant qui a montré le meilleur résultat.

6. En cas d'égalité de résultats, la place la plus élevée est occupée par le participant qui a obtenu le meilleur résultat le plus tôt.

Lors de la compétition, un protocole est rempli dont chaque ligne décrit un jeu et contient le résultat du participant et son nom de jeu. Le protocole est formé en temps réel pendant le championnat, de sorte que les lignes qu'il contient sont disposées dans l'ordre des jeux : plus une ligne apparaît tôt dans le protocole, plus tôt le jeu correspondant à cette ligne s'est terminé. Rédigez un programme efficace, y compris de mémoire, qui, selon le protocole, détermine le gagnant et les lauréats. Il est garanti qu'au moins trois joueurs participent au championnat.

Avant le texte du programme, décrivez brièvement l'algorithme de résolution du problème et indiquez le langage de programmation utilisé et sa version.

Description des données d'entrée

La première ligne contient le nombre N - le nombre total de lignes de protocole. Chacune des N lignes suivantes contient le résultat du participant (un entier non négatif ne dépassant pas 100 millions) et le nom du jeu (le nom ne peut pas contenir d'espaces) séparés par un espace. Les lignes des données initiales correspondent aux lignes du protocole et sont disposées dans le même ordre que dans le protocole.

Il est garanti que le nombre de participants au concours est d'au moins 3.

Description de la sortie

Le programme doit afficher les noms et les scores des trois meilleurs joueurs en uniforme,

indiqué ci-dessous dans l'exemple.

Exemple de saisie :

Exemple de sortie pour l'exemple d'entrée ci-dessus

1 place. qwerty (197128)

2ème place. Alexandre (95715)

3ème place. Jack (95715)

Explication.

Pour chaque joueur, il suffit de connaître le nombre maximum de points qu'il a pu marquer, et le moment auquel ce nombre a été marqué. Nous enregistrerons pour chaque joueur un nom, le nombre maximum de points qu'il a marqués jusqu'à présent et l'heure à laquelle ce nombre a été marqué. Lors de l'ajout d'une nouvelle entrée, nous parcourrons la liste et chercherons un joueur avec le nom donné. S'il n'y a pas un tel joueur, ajoutez-le. Si c'est le cas, nous comparons son résultat précédent avec le nouveau et, si nécessaire, le mettons à jour. Une fois toutes les données lues, nous répétons la procédure trois fois : trouvez le joueur avec le nombre maximum de points. S'il y en a plusieurs, on choisit un joueur parmi eux et le temps minimum. Écrivons son résultat. Maintenant, écrivons -1 dans ses points, pour que la prochaine fois il ne soit pas le meilleur.

Vous trouverez ci-dessous le code de solution en Pascal version 2.6.2. Efficace en mémoire et en temps.

var a,a1,a2,a3,i,n:entier long ;

s,s1,s2,s3 :chaîne ;

pour i:=1 à n commencer

si a>a1 alors commencer

si s=s1 alors commencer a1:=a; s1 :=s ; fin

sinon si s=s2 alors commencer a2:=a1; s2 :=s1 ; a1 :=a ; s1 :=s fin

fin sinon si a>a2 alors commence

si s=s2 alors commencer s2:=s; a2 :=a ; fin

sinon si (ss1) alors commencer

fin sinon si a>a3 alors commence

si (ss1) et (ss2) alors commencer

writeln("1 place.",s1," ("",a1,"")");

writeln("Deuxième place.",s2," ("",a2,"")");

writeln("3ème place.",s3," ("",a3,"")");

Vous trouverez ci-dessous le code de solution en Pascal version 2.6.2. Ne pas être efficace en mémoire.

var n, i, j, cnt, p, trouvé, meilleur, premier, ind : entier long ;

nom : tableau de chaînes ;

points, num : tableau d'entiers longs ;

pour i:= 1 à n faire

pour j:= 1 à cnt faire

si s = nom[j] alors

si trouvé = 0 alors

points := -1;

si p > points alors

points := p;

num := je;

pour i:= 1 à 3 faire

pour j:= 1 à cnt faire

si (points[j] > meilleur) ou (points[j] = meilleur) et (num[j] commencent

meilleur:= points[j] ;

writeln(i, "lieu.", nom, "(", points, ")");

Début juin, 31 ans se sont écoulés depuis la création de l'un des jeux informatiques les plus populaires de l'histoire de l'humanité - "Tetris". Un an après sa naissance - le 18 juillet 1985 - la plateforme de jeu la plus célèbre de Russie, Brick Games, est sortie. Ressemblant extérieurement aux smartphones modernes, la console a intégré plusieurs modifications de Tetris à la fois et s'est vendue à des millions d'exemplaires.

A l'occasion du 30e anniversaire de la naissance de la célèbre plateforme de jeu, le site retrace l'histoire de la création de Tetris, ainsi que sa sortie triomphale de la perestroïka URSS vers les marchés du monde entier.

Casse-tête dans un verre

Tetris a été créé en 1984 par Aleksey Pajitnov, un employé du centre de calcul de l'Académie des sciences de l'URSS. Il a travaillé sur le jeu pendant son temps libre depuis son travail principal et voulait se faire plaisir et faire plaisir à ses collègues plutôt que de conquérir l'esprit des joueurs du monde entier.

Alexey Pajitnov a conçu son célèbre jeu après avoir appris à connaître le puzzle. Photo : www.globallookpress.com

L'idée de "Tetris" est venue à Pajitnov en 1984, lorsqu'il s'est familiarisé avec le puzzle du mathématicien américain Salomon Golomb, qui s'appelait pentomino. Son essence était de combiner plusieurs figures en une seule grande. Le développeur a décidé de créer une version informatique de pentomino. En même temps, selon l'idée de l'auteur, dans son jeu, il était nécessaire de collecter des chiffres dans un verre en temps réel. Pajitnov voulait que les figures à cinq éléments tournent autour de leur propre centre de gravité. Ensuite, les ordinateurs dont disposait le Centre de Calcul n'ont pas pu le faire faute de moyens. Le développeur a décidé de réduire le nombre de blocs qui composaient les chiffres à quatre. Il s'est avéré déjà tétramino. Pajitnov a appelé le jeu "Tetris", croisant "tetramino" et "tennis". Comme base, le programmeur a pris sept chiffres, qui ont ensuite constitué l'ensemble classique du jeu. Il ne pouvait être question de graphisme à cette époque, car l'ordinateur Elektronika-60, sur lequel Tetris a été créé, n'avait pas de moniteur, mais seulement un écran affichant des lettres et des chiffres.

Ordinateur Electronics-60M - un jeu a été créé sur un modèle légèrement antérieur. Photo : Commons.wikimedia.org / Sergueï Frolov

La première version du jeu a été créée dans le langage Pascal alors populaire, donc tout semblait plutôt primitif. Seulement huit mois plus tard, Pajitnov a décidé de porter Tetris sur PC. Le développeur n'avait aucune expérience de travail sur un ordinateur personnel. Il a donc attiré pour cette tâche un écolier de 16 ans, Vadim Gerasimov, qui ressemblait à un jeune génie du centre de calcul. Le jeu a été porté sur PC en quatre jours, et environ le même temps a été consacré au débogage des flux de travail. S'en est suivi un travail de six mois sur la couleur et le tableau des records. Un système de protection a également été élaboré, afin que la paternité puisse être prouvée. Tout cela, les programmeurs l'ont fait pendant leur temps libre. Plus tard, le collègue de Pajitnov, Mikhail Potemkin, a porté le jeu sur l'ordinateur Electronics et a ajouté le chargement automatique des "poubelles" alors qu'il y avait déjà des chiffres dans le verre au début du processus.

Le jeu s'est rapidement répandu d'abord à Moscou, puis dans toute l'URSS - il a été copié sur des disquettes. A cette époque, ses créateurs n'en tiraient aucun bénéfice, puisqu'en fait il appartenait au Centre de Calcul.

Vente sans consentement

Tetris a été montré pour la première fois aux étrangers en 1986. A cette époque, des Budapesters de l'Institut des problèmes cybernétiques sont venus à Moscou - le Centre de calcul a collaboré avec lui. Les invités étrangers ont aimé le jeu, après quoi ils l'ont rapidement porté sur les ordinateurs Commodore 64 et Apple 2.

Parmi les invités se trouvait le propriétaire de la société britannique Andromeda Software, Robert Stein, qui a immédiatement décidé d'acheter les droits du jeu. Il a même réussi à obtenir l'approbation de Pajitnov, mais n'a annoncé aucun montant précis. Et la correspondance à cause du "rideau de fer" est restée très longtemps entre eux.

Stein, estimant que l'accord d'achat du jeu soviétique était déjà presque conclu, a proposé Tetris à ses partenaires de Microsoft. Là, cette idée n'a pas suscité beaucoup d'enthousiasme. Juste au cas où, des représentants de l'entreprise ont envoyé l'idée originale de Pajitnov à des collègues américains de Spectrum Holobyte. Ils ont vu un grand potentiel dans Tetris, et Microsoft et Andromeda Software ont réussi à signer un contrat de vente d'un montant de 3 000 livres et de 7 à 15 % des ventes. Le développeur de "Tetris" lui-même est resté complètement dans le noir.

L'entreprenant Stein voulait tout légaliser le plus tôt possible, seulement en URSS, il devait déjà travailler avec le sommet de l'Académie des sciences, et non avec le Centre de calcul, et encore plus avec ses employés ordinaires. Les responsables ne semblaient pas particulièrement intéressés par tout cela. Résultat, le patron d'Andromeda Software est reparti sans rien.

Dans Spectrum Holobyte, ne se doutant pas qu'ils seraient réellement engagés dans le piratage, ils ont finalisé le jeu soviétique. Ils ont ajouté des sketches communistes, des portraits de Russes célèbres à Tetris, et mis les chansons "Korobeiniki" et "Kalinka" comme accompagnement musical. mécanique de jeu n'a pas touché. En 1987, le produit commercial fini allait sortir en Grande-Bretagne et aux États-Unis, seul Stein n'ayant jamais réussi à obtenir les droits de Tetris. Finalement, il a décidé de ne rien dire à personne. En 1988, la version PC du jeu est sortie en Occident.

L'idée du KGB

Le succès du projet fut énorme. En Occident, la nouveauté a vendu une diffusion décente, "Tetris" a reçu de nombreux prix et récompenses. Le jeu pourrait paralyser le travail des bureaux pendant une journée entière, c'est pourquoi il y avait une rumeur selon laquelle, dans le but de nuire à l'économie d'autres pays, il avait été développé dans les profondeurs du KGB.

Pajitnov à cette époque est allé travailler à ELORG («Electronorgtekhnika»), qui a été affecté à l'Académie des sciences. Cette organisation devait défendre les droits internationaux sur Tetris.

En conséquence, Stein a été mis sous pression, notamment avec l'aide des médias occidentaux. Il a accepté les conditions de l'URSS en signant le contrat. Les représentants de Microsoft à l'époque ont demandé au responsable d'Andromeda Sofrware d'acheter les droits des versions console et arcade du jeu aux développeurs, mais pour une raison quelconque, ils ont eux-mêmes vendu les droits de l'arcade à Atari, qui a ensuite revendu le jeu au Séga japonais.

Tetris est sorti sur Game Boy et a acquis une grande popularité dans le monde. Photo : www.globallookpress.com

Stein n'a pas réussi à avancer dans les négociations car il ne pouvait pas payer le contrat aux Russes. Mais au Japon, ils n'ont pas attendu - ils ont sorti "Tetris" à deux millions d'exemplaires sur PC et NES de Nintendo. Ce dernier a pu acheter les droits via plusieurs sociétés, puis, après s'être mis d'accord avec les détenteurs des droits de l'URSS, lancer le jeu sur une Game Boy portable, ce qui a assuré le succès de la console. Dans le même temps, la société japonaise remporte un procès contre Microsoft et Atari, qui doivent se contenter de la seule version arcade de Tetris.

Le Game Boy fourni avec lequel le jeu a été vendu, notamment grâce à l'idée originale de Pajitnov, s'est vendu à plus de 30 millions d'exemplaires au cours des premières années, et environ 15 millions de cartouches avec le jeu ont été vendues. des consoles les plus performantes au monde tout au long de l'histoire du divertissement électronique.

Dans les années 1990, la Russie, toujours en construction économie de marché, la console japonaise n'a pas été facile à acquérir. Beaucoup plus populaire était l'appareil bon marché Brick Game, d'abord lancé pour les pays européens, basé sur l'analogue de Tetris. Il y avait des courses, ainsi que des jeux comme "snake" et "tank battles". À ce casà propos du respect de tout droit sur l'idée originale d'un développeur soviétique, probablement, il n'y avait aucun doute. Et l'appareil est apparu pour la première fois en 1985, alors qu'il restait encore trois ans avant la sortie officielle de Tetris en Europe.

Dans les années 1990, c'est sur cette plateforme que la plupart des gens jouaient à Tetris. Photo: AIF-Pétersbourg / Yana Khvatova

Une partie

Aleksey Pajitnov en 1989, réalisant que beaucoup d'argent pouvait être gagné sur les jeux, s'est associé à un vieil ami Vladimir Pokhilko et à un nouvel ami Henk Rogers, qui négociait la vente de Tetris au Japon. Ils ont créé le studio AnimaTek, qui était engagé dans le développement de jeux de logique et de problèmes d'intelligence artificielle. Certains développements de cette société ont été inclus, par exemple, dans la stratégie méga-populaire des années 1990 Age of Emires. Dans la perestroïka, AnimaTek a ouvert son siège à San Francisco, puis a sorti plusieurs jeux animés, qui n'ont cependant pas été reconnus. Après avoir lancé quelques programmes de modélisation tridimensionnelle, le studio est tombé dans l'oubli.

Alexey Pajitnov avec son partenaire commercial Henk Rogers. Photo : www.globallookpress.com

Pajitnov n'a l'opportunité de gagner des intérêts de Tetris qu'en 1996, lorsque la licence d'origine expire. Le programmeur a immédiatement créé The Tetris Company en collaboration avec Rogers. Le TTC a enregistré "Tetris" en tant que marque et a depuis commencé à contrôler sa légalité.

Au cours de sa vie, Alexey Pajitnov a réussi à créer environ 13 jeux, mais aucun d'entre eux ne s'est approché de la popularité étonnante de Tetris, qui a été joué pendant plusieurs décennies.

Règles du jeu Tetris

(avec des ajouts pour l'expérience Tetris-Psi)

But du jeu: Remplissez autant de lignes horizontales que possible sur le terrain de jeu en plaçant des pièces descendantes et en ne laissant aucun espace vide entre elles. Une séance dure exactement 2 minutes. Les lignes pleines sont automatiquement supprimées, laissant de l'espace pour que le jeu continue.

Actions de forme

Attention : le contrôle s'effectue à l'aide du clavier, pas de la souris .

Touche (à) pour déplacer le chiffre vers la droite

Touche (ß) pour déplacer la forme vers la gauche

Touche (á) pour faire pivoter la figure dans le sens des aiguilles d'une montre

Clé Z pour faire pivoter la figure DANS LE SENS ANTI-HORAIRE

Clé (â ) pour un mouvement accéléré mais LISSE de la figure vers le bas

Clé ( ESPACE) pour déplacer (réinitialiser) IMMÉDIATEMENT la figure vers le bas

Clé Décalage placer la figurine dans la poche (boîte "tenir" dans coin supérieur gauche) et le remplacer par un morceau de la poche. . Au début de la partie, lorsque la poche est vide, la pièce est simplement remplacée par la suivante.

Résultat du jeu et conseils de jeu

1. Les résultats du jeu sont formés à partir de deux indicateurs :

A) Simple est le nombre de lignes qui peuvent être remplies en 2 minutes.

B) Difficile - c'est le nombre de points qui peuvent être marqués en 2 minutes, en tenant compte des bonus pour les combinaisons.

2. À Le nombre de points marqués dans le jeu dépend du nombre de lignes remplies en un coup (un chiffre). 100 points sont donnés pour une ligne. Vous obtiendrez plus de points si vous "remplissez" 2, 3 ou 4 lignes à la fois. Pour 4 lignes à la fois ("Tetris"), vous obtiendrez le plus de points - 1200.

3. Des points bonus (premium) sont également accordés si vous remplissez les lignes d'affilée avec plusieurs mouvements sans lacunes.

4. Un bonus spécial est attribué pour avoir tourné la figure T de la verticale à l'horizontale au dernier moment (c'est ce qu'on appelle le t-spin). Mais… si vous êtes un joueur novice, nous vous déconseillons de maîtriser cette technique. Il est plus important de montrer le résultat maximum dans les deux premières séries - essai et test (obligatoire) - celle pour laquelle vous êtes actuellement prêt.

5. Le super bonus est accordé pour les successifs (sans lignes supprimées dans les mouvements intermédiaires) obtenant les combinaisons les plus élevées ("tetris" et "t-spins"). Dans les compétitions internationales de Tetris, ces combinaisons sont appelées dos à dos.

6. Pour planifier le placement des formes, utilisez le conseil dans droit champ supplémentaire - il montre la future séquence de chiffres ("file d'attente").

7. A quoi sert la poche (touche Maj) ?

MAIS) Selon la stratégie du jeu, vous aurez peut-être besoin d'une pièce qui apparaît "rarement". Si elle est apparue, mais pas à l'heure, en utilisant une poche (boîte "tenir" dans coin supérieur gauche), vous pouvez l'enregistrer jusqu'au "bon" moment.

B) La poche est utile si un personnage "inconfortable" apparaît qui n'a nulle part où le mettre. Dans ce cas, vous pouvez utiliser la poche comme "annulation temporaire" de la pièce jusqu'à ce qu'il vous convienne de l'utiliser.

Début et fin du jeu, sessions et astuces

8. Jeu sur le site-psycho-ludothèque www. *****/tetris ne peut être lancé que par des joueurs inscrits ayant préalablement rempli 2 questionnaires inclus dans le programme d'expérimentation.

9. Si vous le souhaitez, entre les sessions de la série, vous pouvez faire des pauses de n'importe quelle durée. Cependant, pour que vous soyez crédité d'avoir terminé stade de jeu expérience, vous ne devez PAS vous déconnecter pendant ces pauses.

ATTENTION : Entre les séries, vous pouvez faire une pause même de plusieurs jours, c'est-à-dire que vous pouvez laisser votre page personnelle jusqu'à la prochaine autorisation. Mais l'essentiel est de respecter les délais de l'expérience.

10. Si le terrain de jeu est plein, votre session de jeu peut se terminer plus tôt (avant l'expiration des 2 minutes).

11. Exactement 10 secondes avant la fin de la session, la fenêtre "temps" commencera à clignoter en rouge - cela signifie qu'il est temps de terminer les combinaisons commencées.

12. Le jeu a accompagnement sonore. Si vous aimez jouer avec les sons, vous pouvez connecter des haut-parleurs ou des écouteurs.

13. Les séries créditées (obligatoires) ne seront disponibles qu'une seule fois. Après avoir terminé la série, vous pouvez vous améliorer dans le jeu et améliorer vos résultats à l'aide de séries supplémentaires (facultatives) de cinq matchs chacune. Les résultats ne seront enregistrés que lorsque vous terminerez la série jusqu'à la fin.

14. Si vous avez oublié certaines règles, vous pouvez utiliser l'indice ( brève instruction) - il est situé sous le terrain de jeu.

15. Immédiatement après la fin de chaque session de 2 minutes, en haut de la fenêtre de jeu, vous verrez le nombre de "lignes dégagées" (c'est l'indicateur principal) et le nombre de points marqués (c'est un indicateur auxiliaire) .

16. Dans l'expérience "Teris-Psi", pour chaque série de jeux, un classement interne des joueurs inscrits - participants à l'expérience est créé. Une place plus élevée dans le classement est occupée par les joueurs qui ont un record personnel plus élevé pour le nombre de "lignes dégagées". Si ces records personnels sont égaux, la place la plus élevée dans le classement est occupée par le joueur qui a marqué le plus de points.

Partager: