Robots: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Java}}: link to Java entry)
m (syntax highlighting fixup automation)
 
(16 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{draft task|Games}}{{wikipedia|Robots_(computer_game)}}
{{draft task|Games}}{{wikipedia|Robots_(1984_video_game)}}


<br>
<br>
The task is to implement a clone of Ken Arnold's turn-based game [[wp:Robots_(computer_game)|Robots]].
The task is to implement a clone of Ken Arnold's turn-based game [[wp:Robots_(1984_video_game)|Robots]].


Simple game where its only objective is to escape from a number of robots, which have been programmed to kill the player.
Simple game where its only objective is to escape from a number of robots, which have been programmed to kill the player.
<br><br>
<br><br>



=={{header|C++}}==
=={{header|C++}}==
Windows Console implementation - No safe teleport is implemeted, just the random one.
[[File:robotsCpp.png|200px|thumb|right]]
<lang cpp>
#include <windows.h>
#include <iostream>
#include <ctime>


See [[Robots/C++]].
const int WID = 62, HEI = 42, INC = 10;


=={{header|Common Lisp}}==
class coord : public COORD {

public:
See [[Robots/Common Lisp]].
coord( short x = 0, short y = 0 ) { set( x, y ); }

void set( short x, short y ) { X = x; Y = y; }
=={{header|Go}}==
};

class winConsole {
See [[Robots/Go]].
public:

static winConsole* getInstamnce() {
=={{header|J}}==
if( 0 == inst ) {

inst = new winConsole();
This approximately emulates the bsd robots game. There's a few differences (the game board is larger and has an explicitly displayed junk border, to quit early you close the window, ...), but the fundamental mechanics and display should be pretty close.
}

return inst;
We use two callbacks here: 'game_handler' to capture keyboard events, and 'sys_timer_z_' to capture timer events when the user uses the 'wait for game over' option.
}

void showCursor( bool s ) {
<syntaxhighlight lang="j">require'~addons/ide/qt/gl2.ijs'
CONSOLE_CURSOR_INFO ci = { 1, s };
coinsert'jgl2'
SetConsoleCursorInfo( conOut, &ci );

}
move_handler=: {{
void setColor( WORD clr ) { SetConsoleTextAttribute( conOut, clr ); }
if. 'char'-:systype do.wd'timer 0'
void setCursor( coord p ) { SetConsoleCursorPosition( conOut, p ); }
select.{.tolower sysdata
void setSize( int w, int h ) {
case.'y'do.move _1 _1
coord crd( w + 1, h + 1 );
case.'k'do.move 0 _1
SetConsoleScreenBufferSize( conOut, crd );
case.'u'do.move 1 _1
SMALL_RECT rc = { 0, 0, WID, HEI };
case.'h'do.move _1 0
SetConsoleWindowInfo( conOut, TRUE, &rc );
case.' 'do.move 0 0
}
case.'l'do.move 1 0
void flush() { FlushConsoleInputBuffer( conIn ); }
case.'b'do.move _1 1
void kill() { delete inst; }
case.'j'do.move 0 1
private:
case.'n'do.move 1 1
winConsole() { conOut = GetStdHandle( STD_OUTPUT_HANDLE );
case.'w'do.giveup''
conIn = GetStdHandle( STD_INPUT_HANDLE ); showCursor( false ); }
case.'t'do.teleport''
static winConsole* inst;
end.
HANDLE conOut, conIn;
end.
};
}}
class robots {

public:
Directions=:({.~ i.&'0'){{)n
robots() {
Directions:
console = winConsole::getInstamnce();

console->setSize( WID, HEI );
}
y k u
\|/
~robots() { console->kill(); }
h- -l
void play() {
/|\
char g; do {
b j n
console->showCursor( false );

robotsCount = 10; score = 0; alive = true;
Commands:
clearBoard(); cursor.set( rand() % ( WID - 2 ) + 1, rand() % ( HEI - 2 ) + 1 );

brd[cursor.X + WID * cursor.Y] = '@'; createBoard();
w: wait for end
do{
t: teleport
displayBoard(); getInput();

if( !aliveRobots ) {
Legend:
robotsCount += INC; clearBoard();

brd[cursor.X + WID * cursor.Y] = '@'; createBoard();
+: robot
}
*: junk heap
} while( alive );
@: you
displayBoard(); console->setCursor( coord( 0, 24 ) ); console->setColor( 0x07 );

console->setCursor( coord( 10, 8 ) );
Score: 0
std::cout << "+----------------------------------------+";
}}
console->setCursor( coord( 10, 9 ) );

std::cout << "| GAME OVER |";
query_handler=: {{game_handler=: m&{{if.'char'-:systype do.x`]@.('ny'i.{.sysdata)0 end.}}}}
console->setCursor( coord( 10, 10 ) );
teleport=: {{move (dim#:?*/dim)-player}}
std::cout << "| PLAY AGAIN(Y/N)? |";
start=: {{initlevel 1[score=: 0}}
console->setCursor( coord( 10, 11 ) );
advance=: {{initlevel level+1}}
std::cout << "+----------------------------------------+";
color=: [ gltextcolor@glrgb@{{<.0.5+255*y}}
console->setCursor( coord( 39, 10 ) ); console->showCursor( true );
at=: (gltext@[ [ gltextxy@])"1
console->flush(); std::cin >> g;
dim=: 110 72
} while( g == 'Y' || g == 'y' );
has=: +./ .=
}

private:
showscore=: {{
void clearBoard() {
t=. ];._2 LF,~Directions,":y
for( int y = 0; y < HEI; y++ ) {
t at"_1] 1130,.14*2+i.#t
for( int x = 0; x < WID; x++ ) {
botrow=. I. '+' e."1 >t
brd[x + WID * y] = 32;
'+' at 1130,14*2+botrow color 1 0 0
if( x == 0 || x == WID - 1 || y == 0 || y == HEI - 1 )
'*' at 1130,14*3+botrow color 1 0 1*0.5
brd[x + WID * y] = '#';
'@' at 1130,14*4+botrow color 0 1 0.75
}
}}
}

}
initlevel=: {{
void createBoard() {
game_handler=: move_handler
aliveRobots = robotsCount;
junk=:(#~ has&(dim-1) +. has&0)dim#:i.*/dim
int a, b; for( int x = 0; x < robotsCount; x++ ) {
'player bots'=: ({.;}.) 1+(dim-2) #: (1+10*y) ? */dim-2
do {
drawboard level=: y
a = rand() % WID; b = rand() % HEI;
}}
} while( brd[a + WID * b] != 32 );

brd[a + WID * b] = '+';
drawboard=: {{
}
glclear''
printScore();
glfont '"courier" 12'
}
showscore score color 0 0 0
void displayBoard() {
'+' at 10*bots color 1 0 0
char t; console->setCursor( coord() );
for( int y = 0; y < HEI; y++ ) {
'*' at 10*junk color 1 1 0*0.5
'@' at 10*player color 0 1 0*0.75
for( int x = 0; x < WID; x++ ) {
glpaint''
t = brd[x + WID * y];
}}
switch( t ) {

case ' ': console->setColor( 0x00 ); break;
move=: {{
case '#': console->setColor( 0x09 ); break;
player=: player+y
case '+': console->setColor( 0x0e ); break;
'hazards crashes'=.(~.;1<#/.~) (2#junk),bots-*bots-"1 player
case 'Å': case '*': console->setColor( 0x0c ); break;
junk=: hazards#~crashes
case '@': console->setColor( 0x0a );
bots=: hazards#~crashes=0
}
score=: level#.5 5,-#bots
std::cout << t;
drawboard''
}
if.player e.junk,bots do.lose''
std::cout << "\n";
elseif.0=#bots do.win'' end.
}
}}
}

void getInput() {
lose=: {{
while( 1 ) {
wd'timer 0'
if( ( GetAsyncKeyState( 'Q' ) & 0x8000 ) && cursor.X > 1 && cursor.Y > 1 )
glfont '"courier" 96'
{ execute( -1, -1 ); break; }
game_handler=: quit`start query_handler
if( ( GetAsyncKeyState( 'W' ) & 0x8000 ) && cursor.Y > 1 )
'Game Over' at 320 320 color 1 0 0
{ execute( 0, -1 ); break; }
glfont '"courier" 24'
if( ( GetAsyncKeyState( 'E' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y > 1 )
'Start over? (y/n)' at 480 480 color 0 0 0
{ execute( 1, -1 ); break; }
}}
if( ( GetAsyncKeyState( 'A' ) & 0x8000 ) && cursor.X > 1 )

{ execute( -1, 0 ); break; }
win=: {{
if( ( GetAsyncKeyState( 'D' ) & 0x8000 ) && cursor.X < WID - 2 )
glfont '"courier" 96'
{ execute( 1, 0 ); break; }
game_handler=: quit`advance query_handler
if( ( GetAsyncKeyState( 'Y' ) & 0x8000 ) && cursor.X > 1 && cursor.Y < HEI - 2 )
'You Win' at 320 320 color 0 1 0
{ execute( -1, 1 ); break; }
glfont '"courier" 24'
if( ( GetAsyncKeyState( 'X' ) & 0x8000 ) && cursor.Y < HEI - 2 )
'Continue? (y/n)' at 480 480 color 0 0 0
{ execute( 0, 1 ); break; }
}}
if( ( GetAsyncKeyState( 'C' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y < HEI - 2 )

{ execute( 1, 1 ); break; }
giveup=: {{
if( ( GetAsyncKeyState( 'T' ) & 0x8000 ) )
sys_timer_z_=: {{move_base_ 0 0}}
{ teleport(); moveRobots(); break; }
wd'timer 100'
if( ( GetAsyncKeyState( 'Z' ) & 0x8000 ) )
}}
{ waitForEnd(); break; }

}
wd'pc game closeok; setp wh 1280 720; cc chase isidraw flush;pshow'
console->flush(); printScore();
start''</syntaxhighlight>
}
void teleport() {
brd[cursor.X + WID * cursor.Y] = 32;
cursor.X = rand() % ( WID - 2 ) + 1;
cursor.Y = rand() % ( HEI - 2 ) + 1;
int x = cursor.X + WID * cursor.Y;
if( brd[x] == '*' || brd[x] == '+' || brd[x] == '~' ) {
alive = false; brd[x] = 'Å';
} else brd[x] = '@';
}
void printScore() {
console->setCursor( coord( 0, HEI ) ); console->setColor( 0x2a );
std::cout << " SCORE: " << score << " ";
}
void execute( int x, int y ) {
brd[cursor.X + WID * cursor.Y] = 32; cursor.X += x; cursor.Y += y;
brd[cursor.X + WID * cursor.Y] = '@'; moveRobots();
}
void waitForEnd() {
while( aliveRobots && alive ) {
moveRobots(); displayBoard(); Sleep( 500 );
}
}
void moveRobots() {
int tx, ty;
for( int y = 0; y < HEI; y++ ) {
for( int x = 0; x < WID; x++ ) {
if( brd[x + WID * y] != '+' ) continue;
tx = x; ty = y;
if( tx < cursor.X ) tx++; else if( tx > cursor.X ) tx--;
if( ty < cursor.Y ) ty++; else if( ty > cursor.Y ) ty--;
if( tx != x || ty != y ) {
brd[x + WID * y] = 32;
if( brd[tx + WID * ty] == 32 ) brd[tx + WID * ty] = '~';
else checkCollision( tx, ty );
}
}
}
for( int x = 0; x < WID * HEI; x++ ) {
if( brd[x] == '~') brd[x] = '+';
}
}
void checkCollision( int x, int y ) {
if( cursor.X == x && cursor.Y == y ) {
alive = false; brd[x + y * WID] = 'Å'; return;
}
x = x + y * WID;
if( brd[x] == '*' || brd[x] == '+' || brd[x] == '~' ) {
if( brd[x] != '*' ) { aliveRobots--; score++; }
brd[x] = '*'; aliveRobots--; score++;
}
}
winConsole* console; char brd[WID * HEI];
int robotsCount, score, aliveRobots;
coord cursor; bool alive;
};
winConsole* winConsole::inst = 0;
int main( int argc, char* argv[] ) {
srand( ( unsigned )time( 0 ) );
SetConsoleTitle( "Robots" );
robots g; g.play(); return 0;
}
</lang>


=={{header|Java}}==
=={{header|Java}}==


See [[Robots/Java]].
See [[Robots/Java]].

=={{header|Julia}}==

See [[Robots/Julia]]


=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Java}}
<lang scala>// version 1.1.51


See [[Robots/Kotlin]].
import java.util.Random
import java.awt.*
import java.awt.BasicStroke.*
import java.awt.event.*
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.SwingUtilities


=={{header|Phix}}==
val rand = Random()


See [[Robots/Phix]].
val dirs = listOf(
-1 to 1, 0 to 1, 1 to 1, -1 to 0, 1 to 0, -1 to -1, 0 to -1, 1 to -1
)


=={{header|Raku}}==
class Robots : JPanel() {
(formerly Perl 6)
The bots single-mindedly chase you, taking the shortest path, ignoring obstacles. Use arrow keys to navigate your character(╂) around the board. Avoid bots(☗) and hazards(☢). "Kill" bots by causing them to crash into hazards or other bots. A dead bot creates another hazard. If you eliminate all of the bots on the board, another wave will spawn in random positions. If you touch a hazard or are touched by a bot, you die(†).
<syntaxhighlight lang="raku" line>use Term::termios;


constant $saved = Term::termios.new(fd => 1).getattr;
val nRows = 38
constant $termios = Term::termios.new(fd => 1).getattr;
val nCols = 50
# raw mode interferes with carriage returns, so
val dash = BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f, floatArrayOf(5.0f), 0.0f)
# set flags needed to emulate it manually
$termios.unset_iflags(<BRKINT ICRNL ISTRIP IXON>);
$termios.unset_lflags(< ECHO ICANON IEXTEN ISIG>);
$termios.setattr(:DRAIN);


# reset terminal to original settings and clean up on exit
var playerRow = 0
END { $saved.setattr(:NOW); print "\e[?25h\n" }
var playerCol = 0
var score = 0
var hiScore = 0
var level = 0
var gameOver = true


print "\e[?25l"; # hide cursor
enum class Grid(val symbol: String) {
Player("@"), Robot("+"), Scrap("*"), Mark("~")
}


my %dir = (
lateinit var grid: Array<Array<Grid?>>
"\e[A" => 'up',
"\e[B" => 'down',
"\e[C" => 'right',
"\e[D" => 'left',
);


my $x = 100; # nominal "board" width
init {
my $y = 40; # nominal "board" height
preferredSize = Dimension(800, 650)
background = Color.white
foreground = Color.lightGray
font = Font("SansSerif", Font.PLAIN, 18)
isFocusable = true


my $human = "\e[0;92m╂\e[0m"; # various
addMouseListener(object : MouseAdapter() {
my $robot = "\e[0;91m☗\e[0m"; # entity
override fun mousePressed(e: MouseEvent) {
my $block = "\e[0;93m☢\e[0m"; # sprite
if (gameOver) {
my $dead = "\e[1;37m†\e[0m"; # characters
startNewGame()
my $wall = "\e[1;96m█\e[0m";
repaint()
my $blank = ' ';
}
}
})


my $numbots = 10; # number of bots in each round
addKeyListener(object : KeyAdapter() {
override fun keyPressed(e: KeyEvent) {
if (gameOver) return // disable keystrokes until game starts
val keyCode = e.keyCode
if (keyCode == KeyEvent.VK_NUMPAD5) {
teleport()
}
else {
var k = keyCode - KeyEvent.VK_NUMPAD1
if (k in 0..8) move(if (k > 4) --k else k)
}
repaint()
}
})
}


# blank playing field
fun startNewGame() {
my @scr = flat $wall xx $x, ($wall, $blank xx $x - 2, $wall) xx $y - 2, $wall xx $x;
level = 1
if (score > hiScore) hiScore = score
score = 0
initGrid()
gameOver = false
}


# put player on board
fun initGrid() {
my $me;
grid = Array(nRows) { arrayOfNulls<Grid>(nCols) }
loop {
teleport()
val numRobots = 7 * level
$me = ($x+2 .. ($x - 1 ) * $y).roll;
var i = 0
last if @scr[$me] eq $blank;
}
while (i < numRobots) {
@scr[$me] = $human;
val r = rand.nextInt(nRows)
val c = rand.nextInt(nCols)
if (grid[r][c] == null) {
grid[r][c] = Grid.Robot
i++
}
}
}


# Put an assortment of hazards on board
fun movePlayer(r: Int, c: Int): Boolean {
for ^20 {
if (grid[r][c] != null) {
gameOver = true
my $s = (^$x*$y).pick;
if @scr[$s] eq $blank { @scr[$s] = $block } else { redo }
}
}
else {
grid[playerRow][playerCol] = null
playerRow = r
playerCol = c
grid[r][c] = Grid.Player
}
return !gameOver
}


my $info = 0;
fun move(d: Int) {
my $score = 0;
val c = playerCol + dirs[d].first
val r = playerRow + dirs[d].second


newbots(); # populate board with a fresh wave of bots
if (!withinBounds(r, c)) return
if (!movePlayer(r, c)) return


loop {
for (rr in 0 until nRows) {
print "\e[H\e[J";
for (cc in 0 until nCols) {
print "\e[H";
if (grid[rr][cc] == Grid.Robot) {
print join "\n", @scr.rotor($x)».join;
// calc new r and c based on dx + cc and dy + rr
print "\nSurvived " , $info , ' bots';
val nc = (if (c == cc) 0 else (c - cc) / Math.abs(c - cc)) + cc
val nr = (if (r == rr) 0 else (r - rr) / Math.abs(r - rr)) + rr
if (!withinBounds(nr, nc)) continue
grid[rr][cc] = null


# Read up to 4 bytes from keyboard buffer.
if (grid[nr][nc] == Grid.Player) {
# Page navigation keys are 3-4 bytes each.
gameOver = true
# Specifically, arrow keys are 3.
return /* EARLY RETURN */
}
my $key = $*IN.read(4).decode;
else if (grid[nr][nc] != null) {
score++
if (grid[nr][nc] != Grid.Scrap) score++
grid[nr][nc] = Grid.Scrap
}
else {
// avoid processing the same robot twice
grid[nr][nc] = Grid.Mark
}
}
}
}


move %dir{$key} if so %dir{$key};
var robotsLeft = 0
movebots();
for (rr in 0 until nRows) {
for (cc in 0 until nCols) {
last if $key eq 'q'; # (q)uit
}
if (grid[rr][cc] == Grid.Mark) grid[rr][cc] = Grid.Robot
if (grid[rr][cc] == Grid.Robot) robotsLeft++
}
}
if (robotsLeft == 0) {
level++
initGrid()
}
}


proto sub move (|) {*};
fun teleport() {

movePlayer(rand.nextInt(nRows), rand.nextInt(nCols))
multi move ('up') {
if @scr[$me - $x] ne $wall {
expire() if @scr[$me - $x] ne $blank;
@scr[$me] = $blank;
$me = $me - $x;
@scr[$me] = $human;
}
}
}
multi move ('down') {
if @scr[$me + $x] ne $wall {
expire() if @scr[$me + $x] ne $blank;
@scr[$me] = $blank;
$me = $me + $x;
@scr[$me] = $human;
}
}
multi move ('left') {
if @scr[$me - 1] ne $wall {
expire() if @scr[$me - 1] ne $blank;
@scr[$me] = $blank;
$me = $me - 1;
@scr[$me] = $human;
}
}


multi move ('right') {
fun drawBorder(g: Graphics2D) {
g.stroke = dash
if @scr[$me + 1] ne $wall {
g.color = foreground
expire() if @scr[$me + 1] ne $blank;
@scr[$me] = $blank;
g.drawRect(22, 20, width - 41, height - 72)
$me = $me + 1;
@scr[$me] = $human;
}
}
}


sub newbots {
fun drawGrid(g: Graphics2D) {
for (r in 0 until nRows) {
for ^$numbots {
for (c in 0 until nCols) {
my $s = (^$x*$y).pick;
if (grid[r][c] != null)
if @scr[$s] eq $blank {
@scr[$s] = $robot;
g.drawString(grid[r][c]!!.symbol, 24 + c * 15, 36 + r * 15)
}
} else {
redo
}
}
}
}
}


sub movebots {
fun drawStartScreen(g: Graphics2D) {
g.color = Color.gray
my $mx = $me % $x;
my $my = $me div $x;
g.font = Font("SansSerif", Font.BOLD, 48)
g.drawString("robots", 315, 280)
my @bots = @scr.grep: * eq $robot, :k;
for @bots -> $b {

g.font = this.font
my $bx = $b % $x;
g.drawString("(use numpad to move player)", 270, 350)
my $by = $b div $x ;
g.drawString("(teleport is numpad 5)", 300, 380)
if ($mx - $bx).abs < ($my - $by).abs {
g.drawString("(click to start)", 328, 410)
$by += ($my - $by) < 0 ?? -1 !! 1;
} else {
$bx += ($mx - $bx) < 0 ?? -1 !! 1;
}
my $n = $by * $x + $bx;
if @scr[$n] eq $robot {
@scr[$b] = @scr[$n] = $block;
} elsif @scr[$n] eq $block {
@scr[$b] = $block;
} elsif $n == $me {
expire()
} else {
@scr[$b] = $blank;
@scr[$n] = $robot;
}
}
}
unless +@bots > 0 {

newbots();
fun drawScore(g: Graphics2D) {
g.color = Color.gray
$score += $numbots;
g.font = this.font
val s = String.format("hiscore %s score %s", hiScore, score)
g.drawString(s, 30, height - 17)
}
}
$info = $score + $numbots - @scr.grep: * eq $robot;
}


sub expire {
fun withinBounds(r: Int, c: Int) = (c in 0 until nCols) && (r in 0 until nRows)
@scr[$me] = $dead;
print "\e[H\e[J";
print "\e[H";
print join "\n", @scr.rotor($x)».join;
print "\nSurvived " , $info , ' bots, but succumbed in the end.';
exit
}</syntaxhighlight>
{{out|Sample game}}
<pre>████████████████████████████████████████████████████████████████████████████████████████████████████
█ █
█ ☗ █
█ ☢☢ █
█ † ☢ ☢ ☢ █
█ ☢ ☢☢☢☢☢☢ █
█ ☢☢☢☢☢☢☢ ☢☢☢☢☢☢☢ █
█ ☢☢☢☢ ☢ ☢☢ ☢☢☢ █
█ ☢☢☢☢☢ ☢☢ █
█ ☢☢☢☢☢☢☢☢ ☢☢☢ ☢☢☢ █
█ ☢ ☢☢☢☢ ☢ █
█ ☢☢☢ █
█ ☗ █
█ ☢☢☢ ☢ █
█ ☢☢☢☢☢☢ █
█ ☢☢☢☢☢☢☢☢ █
█ ☢☢☢☢☢☢ ☢☢ █
█ ☢☢☢☢☢☢☢☢ ☗ █
█ ☢☢☢☢☢☢☢ ☢ ☢ █
█ ☢☢ ☢ ☢☢ █
█ ☢ ☢ ☢ ☢☢ █
█ ☢☢ ☢ █
█ ☢ ☢ █
█ ☢ █
█ ☢ █
█ █
█ ☢ ☢ █
█ █
█ █
█ █
█ ☢ █
█ ☢ ☢ █
█ ☢ █
█ █
█ █
█ ☢☢ █
█ ☢ █
█ █
█ ☢☢ █
████████████████████████████████████████████████████████████████████████████████████████████████████
Survived 117 bots, but succumbed in the end.</pre>


=={{header|Wren}}==
override fun paintComponent(gg: Graphics) {
super.paintComponent(gg)
val g = gg as Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON)
drawBorder(g)
drawScore(g)
if (gameOver) drawStartScreen(g)
else drawGrid(g)
}
}


See [[Robots/Wren]].
fun main(args: Array<String>) {
SwingUtilities.invokeLater {
val f = JFrame()
with (f) {
defaultCloseOperation = JFrame.EXIT_ON_CLOSE
title = "Robots"
isResizable = false
add(Robots(), BorderLayout.CENTER)
pack()
setLocationRelativeTo(null)
isVisible = true
}
}
}</lang>

Latest revision as of 12:46, 28 August 2022

Robots is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at Robots_(1984_video_game). The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)


The task is to implement a clone of Ken Arnold's turn-based game Robots.

Simple game where its only objective is to escape from a number of robots, which have been programmed to kill the player.

C++

See Robots/C++.

Common Lisp

See Robots/Common Lisp.

Go

See Robots/Go.

J

This approximately emulates the bsd robots game. There's a few differences (the game board is larger and has an explicitly displayed junk border, to quit early you close the window, ...), but the fundamental mechanics and display should be pretty close.

We use two callbacks here: 'game_handler' to capture keyboard events, and 'sys_timer_z_' to capture timer events when the user uses the 'wait for game over' option.

require'~addons/ide/qt/gl2.ijs'
coinsert'jgl2'

move_handler=: {{
  if. 'char'-:systype do.wd'timer 0'
    select.{.tolower sysdata
      case.'y'do.move _1 _1
      case.'k'do.move  0 _1
      case.'u'do.move  1 _1
      case.'h'do.move _1  0
      case.' 'do.move  0  0
      case.'l'do.move  1  0
      case.'b'do.move _1  1
      case.'j'do.move  0  1
      case.'n'do.move  1  1
      case.'w'do.giveup''
      case.'t'do.teleport''
    end.
  end.
}}

Directions=:({.~ i.&'0'){{)n
Directions:

y k u
 \|/
h- -l
 /|\
b j n

Commands:

w: wait for end
t: teleport

Legend:

+: robot
*: junk heap
@: you

Score: 0
}}

query_handler=: {{game_handler=: m&{{if.'char'-:systype do.x`]@.('ny'i.{.sysdata)0 end.}}}}
teleport=: {{move (dim#:?*/dim)-player}}
start=: {{initlevel 1[score=: 0}}
advance=: {{initlevel level+1}}
color=: [ gltextcolor@glrgb@{{<.0.5+255*y}}
at=: (gltext@[ [ gltextxy@])"1
dim=: 110 72
has=: +./ .=

showscore=: {{
  t=. ];._2 LF,~Directions,":y
  t at"_1] 1130,.14*2+i.#t
  botrow=. I. '+' e."1 >t
  '+' at 1130,14*2+botrow color 1 0 0  
  '*' at 1130,14*3+botrow color 1 0 1*0.5
  '@' at 1130,14*4+botrow color 0 1 0.75
}}

initlevel=: {{
  game_handler=: move_handler
  junk=:(#~ has&(dim-1) +. has&0)dim#:i.*/dim
  'player bots'=: ({.;}.) 1+(dim-2) #: (1+10*y) ? */dim-2
  drawboard level=: y
}}

drawboard=: {{
  glclear''
  glfont '"courier" 12' 
  showscore score   color 0 0 0
  '+' at 10*bots    color 1 0 0
  '*' at 10*junk    color 1 1 0*0.5
  '@' at 10*player  color 0 1 0*0.75
  glpaint''
}}

move=: {{
  player=: player+y
  'hazards crashes'=.(~.;1<#/.~) (2#junk),bots-*bots-"1 player
  junk=: hazards#~crashes
  bots=: hazards#~crashes=0
  score=: level#.5 5,-#bots
  drawboard''
  if.player e.junk,bots do.lose''
  elseif.0=#bots do.win'' end.
}}

lose=: {{
  wd'timer 0'
  glfont '"courier" 96'
  game_handler=: quit`start query_handler
  'Game Over' at 320 320  color 1 0 0
  glfont '"courier" 24'
  'Start over? (y/n)' at 480 480 color 0 0 0
}}

win=: {{
  glfont '"courier" 96'
  game_handler=: quit`advance query_handler
  'You Win' at 320 320  color 0 1 0
  glfont '"courier" 24'
  'Continue? (y/n)' at 480 480 color 0 0 0
}}

giveup=: {{
  sys_timer_z_=: {{move_base_ 0 0}}
  wd'timer 100'
}}

wd'pc game closeok; setp wh 1280 720; cc chase isidraw flush;pshow'
start''

Java

See Robots/Java.

Julia

See Robots/Julia

Kotlin

See Robots/Kotlin.

Phix

See Robots/Phix.

Raku

(formerly Perl 6) The bots single-mindedly chase you, taking the shortest path, ignoring obstacles. Use arrow keys to navigate your character(╂) around the board. Avoid bots(☗) and hazards(☢). "Kill" bots by causing them to crash into hazards or other bots. A dead bot creates another hazard. If you eliminate all of the bots on the board, another wave will spawn in random positions. If you touch a hazard or are touched by a bot, you die(†).

use Term::termios;

constant $saved   = Term::termios.new(fd => 1).getattr;
constant $termios = Term::termios.new(fd => 1).getattr;
# raw mode interferes with carriage returns, so
# set flags needed to emulate it manually
$termios.unset_iflags(<BRKINT ICRNL ISTRIP IXON>);
$termios.unset_lflags(< ECHO ICANON IEXTEN ISIG>);
$termios.setattr(:DRAIN);

# reset terminal to original settings and clean up on exit
END { $saved.setattr(:NOW);  print "\e[?25h\n" }

print "\e[?25l"; # hide cursor

my %dir = (
   "\e[A" => 'up',
   "\e[B" => 'down',
   "\e[C" => 'right',
   "\e[D" => 'left',
);

my $x = 100; # nominal "board" width
my $y = 40;  # nominal "board" height

my $human = "\e[0;92m╂\e[0m"; # various
my $robot = "\e[0;91m☗\e[0m"; # entity
my $block = "\e[0;93m☢\e[0m"; # sprite
my $dead  = "\e[1;37m†\e[0m"; # characters
my $wall  = "\e[1;96m█\e[0m";
my $blank = ' ';

my $numbots = 10; # number of bots in each round

# blank playing field
my @scr = flat $wall xx $x, ($wall, $blank xx $x - 2, $wall) xx $y - 2, $wall xx $x;

# put player on board
my $me;
loop {
    $me = ($x+2 .. ($x - 1 ) * $y).roll;
    last if @scr[$me] eq $blank;
}
@scr[$me] = $human;

# Put an assortment of hazards on board
for ^20 {
    my $s = (^$x*$y).pick;
    if @scr[$s] eq $blank { @scr[$s] = $block } else { redo }
}

my $info  = 0;
my $score = 0;

newbots(); # populate board with a fresh wave of bots

loop {
    print "\e[H\e[J";
    print "\e[H";
    print join "\n", @scr.rotor($x)».join;
    print "\nSurvived " , $info , ' bots';

    # Read up to 4 bytes from keyboard buffer.
    # Page navigation keys are 3-4 bytes each.
    # Specifically, arrow keys are 3.
    my $key = $*IN.read(4).decode;

    move %dir{$key} if so %dir{$key};
    movebots();
    last if $key eq 'q'; # (q)uit
}

proto sub move (|) {*};

multi move ('up') {
    if @scr[$me - $x] ne $wall {
        expire() if @scr[$me - $x] ne $blank;
        @scr[$me] = $blank;
        $me = $me - $x;
        @scr[$me] = $human;
    }
}
multi move ('down') {
    if @scr[$me + $x] ne $wall {
        expire() if @scr[$me + $x] ne $blank;
        @scr[$me] = $blank;
        $me = $me + $x;
        @scr[$me] = $human;
    }
}
multi move ('left') {
   if @scr[$me - 1] ne $wall {
        expire() if @scr[$me - 1] ne $blank;
        @scr[$me] = $blank;
        $me = $me - 1;
        @scr[$me] = $human;
    }
}

multi move ('right') {
    if @scr[$me + 1] ne $wall {
        expire() if @scr[$me + 1] ne $blank;
        @scr[$me] = $blank;
        $me = $me + 1;
        @scr[$me] = $human;
    }
}

sub newbots {
    for ^$numbots {
        my $s = (^$x*$y).pick;
        if @scr[$s] eq $blank {
            @scr[$s] = $robot;
        } else {
            redo
        }
    }
}

sub movebots {
    my $mx = $me % $x;
    my $my = $me div $x;
    my @bots = @scr.grep: * eq $robot, :k;
    for @bots -> $b {
        my $bx = $b % $x;
        my $by = $b div $x ;
        if ($mx - $bx).abs < ($my - $by).abs {
            $by += ($my - $by) < 0 ?? -1 !! 1;
        } else {
            $bx += ($mx - $bx) < 0 ?? -1 !! 1;
        }
        my $n = $by * $x + $bx;
        if @scr[$n] eq $robot {
            @scr[$b] = @scr[$n] = $block;
        } elsif @scr[$n] eq $block {
            @scr[$b] = $block;
        } elsif $n == $me {
            expire()
        } else {
            @scr[$b] = $blank;
            @scr[$n] = $robot;
        }
    }
    unless +@bots > 0 {
        newbots();
        $score += $numbots;
    }
    $info = $score + $numbots - @scr.grep: * eq $robot;
}

sub expire {
    @scr[$me] = $dead;
    print "\e[H\e[J";
    print "\e[H";
    print join "\n", @scr.rotor($x)».join;
    print "\nSurvived " , $info , ' bots, but succumbed in the end.';
    exit
}
Sample game:
████████████████████████████████████████████████████████████████████████████████████████████████████
█                                                                                                  █
█                                               ☗                                                  █
█                                 ☢☢                                                               █
█                             †    ☢       ☢                                  ☢                    █
█          ☢                  ☢☢☢☢☢☢                                                               █
█       ☢☢☢☢☢☢☢                ☢☢☢☢☢☢☢                                                             █
█               ☢☢☢☢           ☢  ☢☢                              ☢☢☢                              █
█             ☢☢☢☢☢               ☢☢                                                               █
█            ☢☢☢☢☢☢☢☢             ☢☢☢                        ☢☢☢                                   █
█             ☢ ☢☢☢☢                ☢                                                              █
█              ☢☢☢                                                                                 █
█                                              ☗                                                   █
█               ☢☢☢ ☢                                                                              █
█               ☢☢☢☢☢☢                                                                             █
█                ☢☢☢☢☢☢☢☢                                                                          █
█               ☢☢☢☢☢☢ ☢☢                                                                          █
█               ☢☢☢☢☢☢☢☢                   ☗                                                       █
█               ☢☢☢☢☢☢☢      ☢                                 ☢                                   █
█                 ☢☢ ☢       ☢☢                                                                    █
█                  ☢ ☢       ☢         ☢☢                                                          █
█                 ☢☢                   ☢                                                           █
█           ☢                          ☢                                                           █
█           ☢                                                                                      █
█           ☢                                                                                      █
█                                                                                                  █
█                                                                        ☢                      ☢  █
█                                                                                                  █
█                                                                                                  █
█                                                                                                  █
█                                                                                             ☢    █
█                                                                             ☢             ☢      █
█                                                        ☢                                         █
█                                                                                                  █
█                                                                                                  █
█                                           ☢☢                                                     █
█                                           ☢                                                      █
█                                                                                                  █
█            ☢☢                                                                                    █
████████████████████████████████████████████████████████████████████████████████████████████████████
Survived 117 bots, but succumbed in the end.

Wren

See Robots/Wren.