Robots: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Java}}: link to Java entry)
m (→‎{{header|Kotlin}}: link to Kotlin entry)
Line 214: Line 214:


=={{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

val rand = Random()

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
)

class Robots : JPanel() {

val nRows = 38
val nCols = 50
val dash = BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f, floatArrayOf(5.0f), 0.0f)

var playerRow = 0
var playerCol = 0
var score = 0
var hiScore = 0
var level = 0
var gameOver = true

enum class Grid(val symbol: String) {
Player("@"), Robot("+"), Scrap("*"), Mark("~")
}

lateinit var grid: Array<Array<Grid?>>

init {
preferredSize = Dimension(800, 650)
background = Color.white
foreground = Color.lightGray
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()
}
})
}

fun startNewGame() {
level = 1
if (score > hiScore) hiScore = score
score = 0
initGrid()
gameOver = false
}

fun initGrid() {
grid = Array(nRows) { arrayOfNulls<Grid>(nCols) }
teleport()
val numRobots = 7 * level
var i = 0
while (i < numRobots) {
val r = rand.nextInt(nRows)
val c = rand.nextInt(nCols)
if (grid[r][c] == null) {
grid[r][c] = Grid.Robot
i++
}
}
}

fun movePlayer(r: Int, c: Int): Boolean {
if (grid[r][c] != null) {
gameOver = true
}
else {
grid[playerRow][playerCol] = null
playerRow = r
playerCol = c
grid[r][c] = Grid.Player
}
return !gameOver
}

fun move(d: Int) {
val c = playerCol + dirs[d].first
val r = playerRow + dirs[d].second

if (!withinBounds(r, c)) return
if (!movePlayer(r, c)) return

for (rr in 0 until nRows) {
for (cc in 0 until nCols) {
if (grid[rr][cc] == Grid.Robot) {
// calc new r and c based on dx + cc and dy + rr
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
}
}
}
}

var robotsLeft = 0
for (rr in 0 until nRows) {
for (cc in 0 until nCols) {
if (grid[rr][cc] == Grid.Mark) grid[rr][cc] = Grid.Robot
if (grid[rr][cc] == Grid.Robot) robotsLeft++
}
}
if (robotsLeft == 0) {
level++
initGrid()
}
}

fun teleport() {
movePlayer(rand.nextInt(nRows), rand.nextInt(nCols))
}

fun drawBorder(g: Graphics2D) {
g.stroke = dash
g.color = foreground
g.drawRect(22, 20, width - 41, height - 72)
}

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)
}
}
}

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>

Revision as of 14:01, 30 October 2017

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_(computer_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++

Windows Console implementation - No safe teleport is implemeted, just the random one.

<lang cpp>

  1. include <windows.h>
  2. include <iostream>
  3. include <ctime>

const int WID = 62, HEI = 42, INC = 10;

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>

Java

See Robots/Java.

Kotlin

See Robots/Kotlin.