Robots: Difference between revisions

8,020 bytes removed ,  1 year ago
m
syntax highlighting fixup automation
(Added Kotlin)
m (syntax highlighting fixup automation)
 
(18 intermediate revisions by 7 users not shown)
Line 1:
{{draft task|Games}}{{wikipedia|Robots_(computer_game1984_video_game)}}
 
<br>
The task is to implement a clone of Ken Arnold's turn-based game [[wp:Robots_(computer_game1984_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.
<br><br>
 
 
=={{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:
coord( short x = 0, short y = 0 ) { set( x, y ); }
void set( short x, short y ) { X = x; Y = y; }
};
class winConsole {
public:
static winConsole* getInstamnce() {
if( 0 == inst ) {
inst = new winConsole();
}
return inst;
}
void showCursor( bool s ) {
CONSOLE_CURSOR_INFO ci = { 1, s };
SetConsoleCursorInfo( conOut, &ci );
}
void setColor( WORD clr ) { SetConsoleTextAttribute( conOut, clr ); }
void setCursor( coord p ) { SetConsoleCursorPosition( conOut, p ); }
void setSize( int w, int h ) {
coord crd( w + 1, h + 1 );
SetConsoleScreenBufferSize( conOut, crd );
SMALL_RECT rc = { 0, 0, WID, HEI };
SetConsoleWindowInfo( conOut, TRUE, &rc );
}
void flush() { FlushConsoleInputBuffer( conIn ); }
void kill() { delete inst; }
private:
winConsole() { conOut = GetStdHandle( STD_OUTPUT_HANDLE );
conIn = GetStdHandle( STD_INPUT_HANDLE ); showCursor( false ); }
static winConsole* inst;
HANDLE conOut, conIn;
};
class robots {
public:
robots() {
console = winConsole::getInstamnce();
console->setSize( WID, HEI );
}
~robots() { console->kill(); }
void play() {
char g; do {
console->showCursor( false );
robotsCount = 10; score = 0; alive = true;
clearBoard(); cursor.set( rand() % ( WID - 2 ) + 1, rand() % ( HEI - 2 ) + 1 );
brd[cursor.X + WID * cursor.Y] = '@'; createBoard();
do{
displayBoard(); getInput();
if( !aliveRobots ) {
robotsCount += INC; clearBoard();
brd[cursor.X + WID * cursor.Y] = '@'; createBoard();
}
} while( alive );
displayBoard(); console->setCursor( coord( 0, 24 ) ); console->setColor( 0x07 );
console->setCursor( coord( 10, 8 ) );
std::cout << "+----------------------------------------+";
console->setCursor( coord( 10, 9 ) );
std::cout << "| GAME OVER |";
console->setCursor( coord( 10, 10 ) );
std::cout << "| PLAY AGAIN(Y/N)? |";
console->setCursor( coord( 10, 11 ) );
std::cout << "+----------------------------------------+";
console->setCursor( coord( 39, 10 ) ); console->showCursor( true );
console->flush(); std::cin >> g;
} while( g == 'Y' || g == 'y' );
}
private:
void clearBoard() {
for( int y = 0; y < HEI; y++ ) {
for( int x = 0; x < WID; x++ ) {
brd[x + WID * y] = 32;
if( x == 0 || x == WID - 1 || y == 0 || y == HEI - 1 )
brd[x + WID * y] = '#';
}
}
}
void createBoard() {
aliveRobots = robotsCount;
int a, b; for( int x = 0; x < robotsCount; x++ ) {
do {
a = rand() % WID; b = rand() % HEI;
} while( brd[a + WID * b] != 32 );
brd[a + WID * b] = '+';
}
printScore();
}
void displayBoard() {
char t; console->setCursor( coord() );
for( int y = 0; y < HEI; y++ ) {
for( int x = 0; x < WID; x++ ) {
t = brd[x + WID * y];
switch( t ) {
case ' ': console->setColor( 0x00 ); break;
case '#': console->setColor( 0x09 ); break;
case '+': console->setColor( 0x0e ); break;
case 'Å': case '*': console->setColor( 0x0c ); break;
case '@': console->setColor( 0x0a );
}
std::cout << t;
}
std::cout << "\n";
}
}
void getInput() {
while( 1 ) {
if( ( GetAsyncKeyState( 'Q' ) & 0x8000 ) && cursor.X > 1 && cursor.Y > 1 )
{ execute( -1, -1 ); break; }
if( ( GetAsyncKeyState( 'W' ) & 0x8000 ) && cursor.Y > 1 )
{ execute( 0, -1 ); break; }
if( ( GetAsyncKeyState( 'E' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y > 1 )
{ execute( 1, -1 ); break; }
if( ( GetAsyncKeyState( 'A' ) & 0x8000 ) && cursor.X > 1 )
{ execute( -1, 0 ); break; }
if( ( GetAsyncKeyState( 'D' ) & 0x8000 ) && cursor.X < WID - 2 )
{ execute( 1, 0 ); break; }
if( ( GetAsyncKeyState( 'Y' ) & 0x8000 ) && cursor.X > 1 && cursor.Y < HEI - 2 )
{ execute( -1, 1 ); break; }
if( ( GetAsyncKeyState( 'X' ) & 0x8000 ) && cursor.Y < HEI - 2 )
{ execute( 0, 1 ); break; }
if( ( GetAsyncKeyState( 'C' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y < HEI - 2 )
{ execute( 1, 1 ); break; }
if( ( GetAsyncKeyState( 'T' ) & 0x8000 ) )
{ teleport(); moveRobots(); break; }
if( ( GetAsyncKeyState( 'Z' ) & 0x8000 ) )
{ waitForEnd(); break; }
}
console->flush(); printScore();
}
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>
 
See [[Robots/Common Lisp]].
=={{header|Java}}==
{{works with|Java|8}}
<lang java>import java.awt.*;
import static java.awt.BasicStroke.*;
import java.awt.event.*;
import static java.lang.Math.abs;
import static java.lang.String.format;
import java.util.Random;
import javax.swing.*;
 
=={{header|Go}}==
public class Robots extends JPanel {
enum Grid {
Player("@"), Robot("+"), Scrap("*"), Mark("~");
 
See [[Robots/Go]].
Grid(String s) {
symbol = s;
}
final String symbol;
}
 
=={{header|J}}==
final static int[][] dirs = {{-1, 1}, {0, 1}, {1, 1}, {-1, 0}, {1, 0},
{-1, -1}, {0, -1}, {1, -1}};
 
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.
final static Random rand = new Random();
 
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.
final int nRows;
final int nCols;
 
<syntaxhighlight lang="j">require'~addons/ide/qt/gl2.ijs'
Grid[][] grid;
coinsert'jgl2'
int playerRow, playerCol, score, hiScore, level;
boolean gameOver = true;
Stroke dash;
 
move_handler=: {{
public Robots() {
if. 'char'-:systype do.wd'timer 0'
setPreferredSize(new Dimension(800, 650));
select.{.tolower sysdata
setBackground(Color.white);
case.'y'do.move _1 _1
setForeground(Color.lightGray);
case.'k'do.move 0 _1
setFont(new Font("SansSerif", Font.PLAIN, 18));
case.'u'do.move 1 _1
setFocusable(true);
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
nRows = 38;
Directions:
nCols = 50;
 
y k u
dash = new BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f,
\|/
new float[]{5.0f}, 0.0f);
h- -l
/|\
b j n
 
Commands:
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (gameOver) {
startNewGame();
repaint();
}
}
});
 
w: wait for end
addKeyListener(new KeyAdapter() {
t: teleport
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
 
Legend:
if (keyCode == KeyEvent.VK_NUMPAD5) {
teleport();
 
+: robot
} else {
*: junk heap
int k = keyCode - KeyEvent.VK_NUMPAD1;
@: you
if (k >= 0 && k < 9) {
move(k > 4 ? --k : k);
}
}
repaint();
}
});
}
 
Score: 0
void startNewGame() {
}}
level = 1;
if (score > hiScore)
hiScore = score;
score = 0;
initGrid();
gameOver = false;
}
 
query_handler=: {{game_handler=: m&{{if.'char'-:systype do.x`]@.('ny'i.{.sysdata)0 end.}}}}
void initGrid() {
teleport=: {{move (dim#:?*/dim)-player}}
grid = new Grid[nRows][nCols];
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=: {{
teleport();
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=: {{
int numRobots = 7 * level;
game_handler=: move_handler
for (int i = 0; i < numRobots;) {
junk=:(#~ has&(dim-1) +. has&0)dim#:i.*/dim
int r = rand.nextInt(nRows);
'player bots'=: ({.;}.) 1+(dim-2) #: (1+10*y) ? */dim-2
int c = rand.nextInt(nCols);
drawboard level=: y
if (grid[r][c] == null) {
}}
grid[r][c] = Grid.Robot;
i++;
}
}
}
 
drawboard=: {{
boolean movePlayer(int r, int c) {
glclear''
if (grid[r][c] != null) {
glfont '"courier" 12'
gameOver = true;
showscore score color 0 }0 else {0
'+' at 10*bots color 1 0 0
grid[playerRow][playerCol] = null;
'*' at 10*junk color 1 1 playerRow = r;0*0.5
'@' at 10*player color 0 1 0*0.75
playerCol = c;
glpaint''
grid[r][c] = Grid.Player;
}}
}
return !gameOver;
}
 
void move(int d)=: {{
player=: player+y
int c = playerCol + dirs[d][0];
'hazards crashes'=.(~.;1<#/.~) (2#junk),bots-*bots-"1 player
int r = playerRow + dirs[d][1];
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=: {{
if (!withinBounds(r, c))
wd'timer 0'
return;
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=: {{
if (!movePlayer(r, c))
glfont '"courier" 96'
return;
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=: {{
for (int rr = 0; rr < nRows; rr++)
sys_timer_z_=: {{move_base_ 0 0}}
for (int cc = 0; cc < nCols; cc++) {
wd'timer 100'
if (grid[rr][cc] == Grid.Robot) {
}}
 
wd'pc game closeok; setp wh 1280 720; cc chase isidraw flush;pshow'
// calc new r and c based on dx + cc and dy + rr
start''</syntaxhighlight>
int nc = (c == cc ? 0 : (c - cc) / abs(c - cc)) + cc;
int nr = (r == rr ? 0 : (r - rr) / abs(r - rr)) + rr;
 
=={{header|Java}}==
if (!withinBounds(nr, nc))
continue;
 
See [[Robots/Java]].
grid[rr][cc] = null;
 
=={{header|Julia}}==
if (grid[nr][nc] == Grid.Player) {
gameOver = true;
return; /* EARLY RETURN */
 
See [[Robots/Julia]]
} else if (grid[nr][nc] != null) {
score++;
if (grid[nr][nc] != Grid.Scrap)
score++;
grid[nr][nc] = Grid.Scrap;
 
=={{header|Kotlin}}==
} else {
// avoid processing the same robot twice
grid[nr][nc] = Grid.Mark;
}
}
}
 
See [[Robots/Kotlin]].
int robotsLeft = 0;
for (int rr = 0; rr < nRows; rr++)
for (int cc = 0; cc < nCols; cc++) {
if (grid[rr][cc] == Grid.Mark)
grid[rr][cc] = Grid.Robot;
if (grid[rr][cc] == Grid.Robot)
robotsLeft++;
}
 
=={{header|Phix}}==
if (robotsLeft == 0) {
level++;
initGrid();
}
}
 
See [[Robots/Phix]].
void teleport() {
movePlayer(rand.nextInt(nRows), rand.nextInt(nCols));
}
 
=={{header|Raku}}==
void drawBorder(Graphics2D g) {
(formerly Perl 6)
g.setStroke(dash);
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(†).
g.setColor(getForeground());
<syntaxhighlight lang="raku" line>use Term::termios;
g.drawRect(22, 20, getWidth() - 41, getHeight() - 72);
}
 
constant $saved = Term::termios.new(fd => 1).getattr;
void drawGrid(Graphics2D g) {
constant $termios = Term::termios.new(fd => 1).getattr;
for (int r = 0; r < nRows; r++)
# raw mode interferes with carriage returns, so
for (int c = 0; c < nCols; c++) {
# set flags needed to emulate it manually
if (grid[r][c] != null)
$termios.unset_iflags(<BRKINT ICRNL ISTRIP IXON>);
g.drawString(grid[r][c].symbol, 24 + c * 15, 36 + r * 15);
$termios.unset_lflags(< ECHO ICANON IEXTEN ISIG>);
}
$termios.setattr(:DRAIN);
}
 
# reset terminal to original settings and clean up on exit
void drawStartScreen(Graphics2D g) {
END { $saved.setattr(:NOW); print "\e[?25h\n" }
g.setColor(Color.gray);
g.setFont(new Font("SansSerif", Font.BOLD, 48));
g.drawString("robots", 315, 280);
 
print "\e[?25l"; # hide cursor
g.setFont(getFont());
g.drawString("(use numpad to move player)", 270, 350);
g.drawString("(teleport is numpad 5)", 300, 380);
g.drawString("(click to start)", 328, 410);
}
 
my %dir = (
void drawScore(Graphics2D g) {
"\e[A" => 'up',
g.setColor(Color.gray);
"\e[B" => 'down',
g.setFont(getFont());
"\e[C" => 'right',
String s = format("hiscore %s score %s", hiScore, score);
"\e[D" => 'left',
g.drawString(s, 30, getHeight() - 17);
);
}
 
my $x = 100; # nominal "board" width
boolean withinBounds(int r, int c) {
my $y = 40; # nominal "board" height
return c >= 0 && c < nCols && r >= 0 && r < nRows;
}
 
my $human = "\e[0;92m╂\e[0m"; # various
@Override
my $robot = "\e[0;91m☗\e[0m"; # entity
public void paintComponent(Graphics gg) {
my $block = "\e[0;93m☢\e[0m"; # sprite
super.paintComponent(gg);
my $dead = "\e[1;37m†\e[0m"; # characters
Graphics2D g = (Graphics2D) gg;
my $wall = "\e[1;96m█\e[0m";
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
my $blank = ' ';
RenderingHints.VALUE_ANTIALIAS_ON);
 
my $numbots = 10; # number of bots in each round
drawBorder(g);
drawScore(g);
if (gameOver) {
drawStartScreen(g);
} else {
drawGrid(g);
}
}
 
# blank playing field
public static void main(String[] args) {
my @scr = flat $wall xx $x, ($wall, $blank xx $x - 2, $wall) xx $y - 2, $wall xx $x;
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Robots");
f.setResizable(false);
f.add(new Robots(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}</lang>
 
# put player on board
=={{header|Kotlin}}==
my $me;
{{trans|Java}}
loop {
<lang scala>// version 1.1.51
$me = ($x+2 .. ($x - 1 ) * $y).roll;
last if @scr[$me] eq $blank;
}
@scr[$me] = $human;
 
# Put an assortment of hazards on board
import java.util.Random
for ^20 {
import java.awt.*
my $s = (^$x*$y).pick;
import java.awt.BasicStroke.*
if @scr[$s] eq $blank { @scr[$s] = $block } else { redo }
import java.awt.event.*
}
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.SwingUtilities
 
my $info = 0;
val rand = Random()
my $score = 0;
 
newbots(); # populate board with a fresh wave of bots
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
)
 
loop {
class Robots : JPanel() {
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.
val nRows = 38
# Page navigation keys are 3-4 bytes each.
val nCols = 50
# Specifically, arrow keys are 3.
val dash = BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f, floatArrayOf(5.0f), 0.0f)
my $key = $*IN.read(4).decode;
 
move %dir{$key} if so %dir{$key};
var playerRow = 0
movebots();
var playerCol = 0
last if $key eq 'q'; # (q)uit
var score = 0
}
var hiScore = 0
var level = 0
var gameOver = true
 
proto sub move (|) {*};
enum class Grid(val symbol: String) {
Player("@"), Robot("+"), Scrap("*"), Mark("~")
}
 
multi move ('up') {
lateinit var grid: Array<Array<Grid?>>
if @scr[$me - $x] ne $wall {
 
expire() if @scr[$me - $x] ne $blank;
init {
preferredSize@scr[$me] = Dimension(800, 650)$blank;
background$me = Color.white$me - $x;
foreground@scr[$me] = Color.lightGray$human;
font = Font("SansSerif", Font.PLAIN, 18)
isFocusable = true
 
addMouseListener(object : MouseAdapter() {
override fun mousePressed(e: MouseEvent) {
if (gameOver) {
startNewGame()
repaint()
}
}
})
 
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()
}
})
}
}
 
multi move ('down') {
fun startNewGame() {
if @scr[$me + $x] levelne =$wall 1{
if expire(score) >if hiScore)@scr[$me + hiScore$x] =ne score$blank;
score@scr[$me] = 0 $blank;
initGrid()$me = $me + $x;
gameOver@scr[$me] = false$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 initGrid() {
if @scr[$me + 1] ne $wall {
grid = Array(nRows) { arrayOfNulls<Grid>(nCols) }
teleportexpire() if @scr[$me + 1] ne $blank;
val numRobots@scr[$me] = 7 * level$blank;
var i$me = 0$me + 1;
while@scr[$me] (i= < numRobots) {$human;
val r = rand.nextInt(nRows)
val c = rand.nextInt(nCols)
if (grid[r][c] == null) {
grid[r][c] = Grid.Robot
i++
}
}
}
}
 
sub newbots {
fun movePlayer(r: Int, c: Int): Boolean {
for ^$numbots {
if (grid[r][c] != null) {
my gameOver$s = true(^$x*$y).pick;
if @scr[$s] eq $blank {
@scr[$s] = $robot;
} else {
redo
}
else {
grid[playerRow][playerCol] = null
playerRow = r
playerCol = c
grid[r][c] = Grid.Player
}
return !gameOver
}
}
 
sub movebots {
fun move(d: Int) {
my val c$mx = playerCol$me +% dirs[d].first$x;
my val r$my = playerRow$me +div dirs[d].second$x;
my @bots = @scr.grep: * eq $robot, :k;
 
for @bots -> $b {
if (!withinBounds(r, c)) return
ifmy (!movePlayer(r,$bx c))= return$b % $x;
my $by = $b div $x ;
 
forif (rr$mx in- 0$bx).abs < ($my until- nRows$by).abs {
for$by += (cc$my in- $by) < 0 until?? nCols)-1 !! {1;
} if (grid[rr][cc] == Grid.Robot)else {
$bx += ($mx - $bx) < 0 ?? //-1 calc new r and c based on dx + cc and dy +!! rr1;
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
 
if (grid[nr][nc] == Grid.Player) {
gameOver = true
return /* EARLY RETURN */
}
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
}
}
}
}
my $n = $by * $x + $bx;
 
varif robotsLeft@scr[$n] =eq 0$robot {
for (rr in 0 until@scr[$b] nRows)= {@scr[$n] = $block;
} elsif @scr[$n] eq for (cc in 0 until nCols)$block {
if (grid[rr][cc] == Grid.Mark) grid[rr]@scr[cc$b] = Grid.Robot$block;
} elsif if (grid[rr][cc]$n == Grid.Robot)$me robotsLeft++{
}expire()
} else {
if (robotsLeft == 0) {@scr[$b] = $blank;
level++@scr[$n] = $robot;
initGrid()
}
}
unless +@bots > 0 {
 
fun teleport newbots() {;
$score += $numbots;
movePlayer(rand.nextInt(nRows), rand.nextInt(nCols))
}
$info = $score + $numbots - @scr.grep: * eq $robot;
}
 
sub expire {
fun drawBorder(g: Graphics2D) {
g.stroke@scr[$me] = dash$dead;
print "\e[H\e[J";
g.color = foreground
print "\e[H";
g.drawRect(22, 20, width - 41, height - 72)
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}}==
fun drawGrid(g: Graphics2D) {
for (r in 0 until nRows) {
for (c in 0 until nCols) {
if (grid[r][c] != null)
g.drawString(grid[r][c]!!.symbol, 24 + c * 15, 36 + r * 15)
}
}
}
 
See [[Robots/Wren]].
fun drawStartScreen(g: Graphics2D) {
g.color = Color.gray
g.font = Font("SansSerif", Font.BOLD, 48)
g.drawString("robots", 315, 280)
 
g.font = this.font
g.drawString("(use numpad to move player)", 270, 350)
g.drawString("(teleport is numpad 5)", 300, 380)
g.drawString("(click to start)", 328, 410)
}
 
fun drawScore(g: Graphics2D) {
g.color = Color.gray
g.font = this.font
val s = String.format("hiscore %s score %s", hiScore, score)
g.drawString(s, 30, height - 17)
}
 
fun withinBounds(r: Int, c: Int) = (c in 0 until nCols) && (r in 0 until nRows)
 
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)
}
}
 
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>
10,327

edits