From 74714d0b22130366abdffb8408279a8cede45e95 Mon Sep 17 00:00:00 2001 From: Marat Vafin Date: Fri, 9 Dec 2016 19:35:07 +0300 Subject: [PATCH 1/4] kotlin starter pack --- .gitignore | 6 ++ airesources/Kotlin/Model.kt | 177 ++++++++++++++++++++++++++++++++ airesources/Kotlin/MyBot.kt | 34 ++++++ airesources/Kotlin/RandomBot.kt | 34 ++++++ airesources/Kotlin/runGame.bat | 3 + airesources/Kotlin/runGame.sh | 5 + 6 files changed, 259 insertions(+) create mode 100644 airesources/Kotlin/Model.kt create mode 100644 airesources/Kotlin/MyBot.kt create mode 100644 airesources/Kotlin/RandomBot.kt create mode 100644 airesources/Kotlin/runGame.bat create mode 100755 airesources/Kotlin/runGame.sh diff --git a/.gitignore b/.gitignore index 51e6d0ca5..b73ba19e4 100644 --- a/.gitignore +++ b/.gitignore @@ -452,3 +452,9 @@ screenlog.* node_modules /dist + + +#################### +## Intellij Idea ## +#################### +.idea/ diff --git a/airesources/Kotlin/Model.kt b/airesources/Kotlin/Model.kt new file mode 100644 index 000000000..839ae2fec --- /dev/null +++ b/airesources/Kotlin/Model.kt @@ -0,0 +1,177 @@ +import java.util.* + +class Networking { + + val SIZE_OF_INTEGER_PREFIX = 4 + val CHAR_SIZE = 1 + var width : Int = 0 + var height : Int = 0 + + val productions = ArrayList>() + + internal fun deserializeGameMapSize(inputString: String) { + val map = inputString.split(" ") + + width = Integer.parseInt(map[0]) + height = Integer.parseInt(map[1]) + } + + + internal fun deserializeProductions(inputString: String) { + val input = inputString.split(" ") + + var index = 0 + for (a in 0..height - 1) { + val row = ArrayList() + for (b in 0..width - 1) { + row.add(Integer.parseInt(input[index])) + index++ + } + productions.add(row) + } + } + + internal fun serializeMoveList(moves: ArrayList): String { + val builder = StringBuilder() + for ((loc, dir) in moves) builder.append(loc.x.toString() + " " + loc.y + " " + dir.ordinal + " ") + return builder.toString() + } + + internal fun deserializeGameMap(inputString: String): GameMap { + val input = inputString.split(" ") + + val map = GameMap(width, height) + + // Run-length encode of owners + var y = 0 + var x = 0 + var counter = 0 + var owner = 0 + var currentIndex = 0 + while (y != map.height) { + counter = Integer.parseInt(input[currentIndex]) + owner = Integer.parseInt(input[currentIndex + 1]) + currentIndex += 2 + for (a in 0..counter - 1) { + map.contents[y][x].owner = owner + ++x + if (x == map.width) { + x = 0 + ++y + } + } + } + + for (a in 0..map.contents.size - 1) { + for (b in 0..map.contents[a].size - 1) { + val strengthInt = Integer.parseInt(input[currentIndex]) + currentIndex++ + map.contents[a][b].strength = strengthInt + map.contents[a][b].production = productions[a][b] + } + } + + return map + } + + internal fun sendString(sendString: String) { + print(sendString + '\n') + System.out.flush() + } + + internal fun getString(): String? { + val builder = StringBuilder() + var buffer = 0 + while (true) { + buffer = System.`in`.read() + if (buffer < 0 || buffer == '\n'.toInt()) { + break + } + builder.append(buffer.toChar()) + } + //Removes a carriage return if on windows for manual testing. + if (builder[builder.length - 1] == '\r') { + builder.setLength(builder.length - 1) + } + return builder.toString() + } + + internal fun getInit(): InitPackage { + val myID = Integer.parseInt(getString()!!).toInt() + deserializeGameMapSize(getString()!!) + deserializeProductions(getString()!!) + val map = deserializeGameMap(getString()!!) + + return InitPackage(myID, map) + } + + internal fun sendInit(name: String) { + sendString(name) + } + + internal fun getFrame(): GameMap { + return deserializeGameMap(getString()!!) + } + + internal fun sendFrame(moves: ArrayList) { + sendString(serializeMoveList(moves)) + } +} + +data class Site(var owner: Int, var strength : Int, var production: Int) +data class Location(var x: Int, var y: Int) +data class InitPackage(var myID: Int, var map: GameMap) +data class Move(var loc: Location, var dir: Direction) + +enum class Direction { + STILL, NORTH, EAST, SOUTH, WEST; + + companion object { + val DIRECTIONS = arrayOf(STILL, NORTH, EAST, SOUTH, WEST) + val CARDINALS = arrayOf(NORTH, EAST, SOUTH, WEST) + + fun random() : Direction { + return DIRECTIONS[Random().nextInt(DIRECTIONS.size)] + } + } +} + +class GameMap(val width: Int, val height: Int) { + + val contents = ArrayList>() + + init { + for (y in 0..height - 1) { + val row = ArrayList() + for (x in 0..width - 1) { + row.add(Site(0, 0, 0)) + } + contents.add(row) + } + } + + fun inBounds(location: Location) : Boolean { + return location.x < width && location.x >= 0 && location.y < height && location.y >= 0 + } + + fun getLocation(loc: Location, dir: Direction): Location { + val l = loc.copy() + when(dir) { + Direction.STILL -> return l + Direction.NORTH -> if (l.y == 0) l.y = height - 1 else l.y-- + Direction.EAST -> if (l.x == width - 1) l.x = 0 else l.x++ + Direction.SOUTH -> if (l.y == height - 1) l.y = 0 else l.y++ + Direction.WEST -> if (l.x == 0) l.x = width - 1 else l.x-- + } + return l + } + + fun getSite(loc: Location, dir: Direction): Site { + val (x, y) = getLocation(loc, dir) + return contents[y][x] + } + + fun getSite(loc: Location): Site { + return contents[loc.y][loc.x] + } +} \ No newline at end of file diff --git a/airesources/Kotlin/MyBot.kt b/airesources/Kotlin/MyBot.kt new file mode 100644 index 000000000..d2c5aba90 --- /dev/null +++ b/airesources/Kotlin/MyBot.kt @@ -0,0 +1,34 @@ +import java.util.* + +fun main(args : Array) { + MyBot().start() +} + +class MyBot { + + fun start() { + val network = Networking() + val iPackage = network.getInit() + val myID = iPackage.myID + var gameMap = iPackage.map + + network.sendInit("MyKotlinBot") + + while (true) { + val moves = ArrayList() + + gameMap = network.getFrame() + + for (y in 0..gameMap.height - 1) { + for (x in 0..gameMap.width - 1) { + val site = gameMap.getSite(Location(x, y)) + if (site.owner == myID) { + val dir = Direction.random() + moves.add(Move(Location(x, y), dir)) + } + } + } + network.sendFrame(moves) + } + } +} \ No newline at end of file diff --git a/airesources/Kotlin/RandomBot.kt b/airesources/Kotlin/RandomBot.kt new file mode 100644 index 000000000..1dd52a943 --- /dev/null +++ b/airesources/Kotlin/RandomBot.kt @@ -0,0 +1,34 @@ +import java.util.* + +fun main(args : Array) { + RandomBot().start() +} + +class RandomBot { + + fun start() { + val network = Networking() + val iPackage = network.getInit() + val myID = iPackage.myID + var gameMap = iPackage.map + + network.sendInit("RandomKotlinBot") + + while (true) { + val moves = ArrayList() + + gameMap = network.getFrame() + + for (y in 0..gameMap.height - 1) { + for (x in 0..gameMap.width - 1) { + val site = gameMap.getSite(Location(x, y)) + if (site.owner == myID) { + val dir = Direction.random() + moves.add(Move(Location(x, y), dir)) + } + } + } + network.sendFrame(moves) + } + } +} \ No newline at end of file diff --git a/airesources/Kotlin/runGame.bat b/airesources/Kotlin/runGame.bat new file mode 100644 index 000000000..a8bcc5b59 --- /dev/null +++ b/airesources/Kotlin/runGame.bat @@ -0,0 +1,3 @@ +kotlinc.bat *.kt -d mybot.jar +kotlinc.bat *.kt -d randombot.jar +.\halite.exe -d "30 30" "kotlin -classpath mybot.jar MyBotKt" "kotlin -classpath randombot.jar RandomBotKt" diff --git a/airesources/Kotlin/runGame.sh b/airesources/Kotlin/runGame.sh new file mode 100755 index 000000000..4995bd935 --- /dev/null +++ b/airesources/Kotlin/runGame.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +kotlinc *.kt -d mybot.jar +kotlinc *.kt -d randombot.jar +./halite -d "30 30" "kotlin -classpath mybot.jar MyBotKt" "kotlin -classpath randombot.jar RandomBotKt" \ No newline at end of file From f1c79eac2ef10ad73008547afd4da84d4ad7b628 Mon Sep 17 00:00:00 2001 From: Marat Vafin Date: Fri, 9 Dec 2016 19:40:18 +0300 Subject: [PATCH 2/4] website stuff --- website/archiveStarterPackages.sh | 5 ++++- website/downloads.php | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/website/archiveStarterPackages.sh b/website/archiveStarterPackages.sh index d8050303e..2dda646cf 100755 --- a/website/archiveStarterPackages.sh +++ b/website/archiveStarterPackages.sh @@ -16,7 +16,8 @@ mkdir Halite-Python-Starter-Package \ Halite-JavaScript-Starter-Package \ Halite-OCaml-Starter-Package \ Halite-Clojure-Starter-Package \ - Halite-C-Starter-Package + Halite-C-Starter-Package \ + Halite-Kotlin-Starter-Package cp -r Python/* Halite-Python-Starter-Package/ cp -r Java/* Halite-Java-Starter-Package/ @@ -31,6 +32,7 @@ cp -r JavaScript/* Halite-JavaScript-Starter-Package/ cp -r OCaml/* Halite-OCaml-Starter-Package/ cp -r Clojure/* Halite-Clojure-Starter-Package/ cp -r C/* Halite-C-Starter-Package/ +cp -r Kotlin/* Halite-Kotlin-Starter-Package/ cp -r Scala/* Halite-Scala-Starter-Package/ rm Halite-Scala-Starter-Package/MyBot.java @@ -48,6 +50,7 @@ zip -r Halite-JavaScript-Starter-Package.zip Halite-JavaScript-Starter-Package/ zip -r Halite-OCaml-Starter-Package.zip Halite-OCaml-Starter-Package/ zip -r Halite-Clojure-Starter-Package.zip Halite-Clojure-Starter-Package/ zip -r Halite-C-Starter-Package.zip Halite-C-Starter-Package/ +zip -r Halite-Kotlin-Starter-Package.zip Halite-Kotlin-Starter-Package/ mkdir -p ../website/downloads/starterpackages mv *.zip ../website/downloads/starterpackages diff --git a/website/downloads.php b/website/downloads.php index 4e02a1b1e..0bffa417d 100644 --- a/website/downloads.php +++ b/website/downloads.php @@ -36,6 +36,7 @@
  • OCaml 4.01.0
  • Clojure 1.8.0
  • C
  • +
  • Kotlin
  • From ee836d14ab6b15212f5718c30bbb6dbaf1723afa Mon Sep 17 00:00:00 2001 From: Marat Vafin Date: Mon, 12 Dec 2016 04:42:24 +0300 Subject: [PATCH 3/4] refactor to more functional way --- airesources/Kotlin/Model.kt | 105 ++++++++++++------------------------ 1 file changed, 34 insertions(+), 71 deletions(-) diff --git a/airesources/Kotlin/Model.kt b/airesources/Kotlin/Model.kt index 839ae2fec..130c27b47 100644 --- a/airesources/Kotlin/Model.kt +++ b/airesources/Kotlin/Model.kt @@ -7,52 +7,38 @@ class Networking { var width : Int = 0 var height : Int = 0 - val productions = ArrayList>() + val productions : MutableList> = arrayListOf() - internal fun deserializeGameMapSize(inputString: String) { - val map = inputString.split(" ") - - width = Integer.parseInt(map[0]) - height = Integer.parseInt(map[1]) + fun deserializeGameMapSize(inputString: String) { + inputString.split(" ") + .map { Integer.parseInt(it) } + .forEachIndexed { index, size -> + if (index == 0) width = size else height = size} } - - internal fun deserializeProductions(inputString: String) { - val input = inputString.split(" ") - - var index = 0 - for (a in 0..height - 1) { - val row = ArrayList() - for (b in 0..width - 1) { - row.add(Integer.parseInt(input[index])) - index++ - } - productions.add(row) - } + fun deserializeProductions(input: String) { + val inputs = input.split(" ").map { Integer.parseInt(it) } + (0 until height).mapTo(productions) { inputs.subList(it * width, (it + 1) * width).toMutableList() } } - internal fun serializeMoveList(moves: ArrayList): String { + fun serializeMoveList(moves: ArrayList): String { val builder = StringBuilder() for ((loc, dir) in moves) builder.append(loc.x.toString() + " " + loc.y + " " + dir.ordinal + " ") return builder.toString() } - internal fun deserializeGameMap(inputString: String): GameMap { - val input = inputString.split(" ") + fun deserializeGameMap(input: String): GameMap { + val inputs = input.split(" ").map { Integer.parseInt(it) } val map = GameMap(width, height) - // Run-length encode of owners var y = 0 var x = 0 - var counter = 0 - var owner = 0 var currentIndex = 0 - while (y != map.height) { - counter = Integer.parseInt(input[currentIndex]) - owner = Integer.parseInt(input[currentIndex + 1]) - currentIndex += 2 - for (a in 0..counter - 1) { + while (y < map.height) { + val counter = inputs[currentIndex++] + val owner = inputs[currentIndex++] + (0 until counter).forEach { map.contents[y][x].owner = owner ++x if (x == map.width) { @@ -62,58 +48,39 @@ class Networking { } } - for (a in 0..map.contents.size - 1) { - for (b in 0..map.contents[a].size - 1) { - val strengthInt = Integer.parseInt(input[currentIndex]) - currentIndex++ - map.contents[a][b].strength = strengthInt - map.contents[a][b].production = productions[a][b] + for (x in 0 until map.contents.size) { + for (y in 0 until map.contents[x].size) { + map.contents[x][y].strength = inputs[currentIndex++] + map.contents[x][y].production = productions[x][y] } } return map } - internal fun sendString(sendString: String) { - print(sendString + '\n') + fun sendString(sendString: String) { + println(sendString) System.out.flush() } - internal fun getString(): String? { - val builder = StringBuilder() - var buffer = 0 - while (true) { - buffer = System.`in`.read() - if (buffer < 0 || buffer == '\n'.toInt()) { - break - } - builder.append(buffer.toChar()) - } - //Removes a carriage return if on windows for manual testing. - if (builder[builder.length - 1] == '\r') { - builder.setLength(builder.length - 1) - } - return builder.toString() - } - - internal fun getInit(): InitPackage { - val myID = Integer.parseInt(getString()!!).toInt() - deserializeGameMapSize(getString()!!) - deserializeProductions(getString()!!) - val map = deserializeGameMap(getString()!!) + fun getInit(): InitPackage { + val myID = Integer.parseInt(readLine()?.trim()) + deserializeGameMapSize(readLine()!!.trim()) + deserializeProductions(readLine()!!.trim()) + val map = deserializeGameMap(readLine()!!.trim()) return InitPackage(myID, map) } - internal fun sendInit(name: String) { + fun sendInit(name: String) { sendString(name) } - internal fun getFrame(): GameMap { - return deserializeGameMap(getString()!!) + fun getFrame(): GameMap { + return deserializeGameMap(readLine()!!.trim()) } - internal fun sendFrame(moves: ArrayList) { + fun sendFrame(moves: ArrayList) { sendString(serializeMoveList(moves)) } } @@ -138,15 +105,11 @@ enum class Direction { class GameMap(val width: Int, val height: Int) { - val contents = ArrayList>() + val contents : MutableList> = arrayListOf() init { - for (y in 0..height - 1) { - val row = ArrayList() - for (x in 0..width - 1) { - row.add(Site(0, 0, 0)) - } - contents.add(row) + (0 until height).forEach { + contents.add(Array(width, {Site(0, 0, 0)}).toMutableList()) } } From ebf1210bcb6589910b99931e340910ceff57e9f0 Mon Sep 17 00:00:00 2001 From: Marat Vafin Date: Thu, 15 Dec 2016 15:14:49 +0300 Subject: [PATCH 4/4] added LANGUAGE file and sh/bat scripts for runGame with building self executable jars --- airesources/Kotlin/LANGUAGE | 1 + airesources/Kotlin/runGameExecutable.bat | 5 +++++ airesources/Kotlin/runGameExecutable.sh | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 airesources/Kotlin/LANGUAGE create mode 100644 airesources/Kotlin/runGameExecutable.bat create mode 100644 airesources/Kotlin/runGameExecutable.sh diff --git a/airesources/Kotlin/LANGUAGE b/airesources/Kotlin/LANGUAGE new file mode 100644 index 000000000..a34f6fd82 --- /dev/null +++ b/airesources/Kotlin/LANGUAGE @@ -0,0 +1 @@ +Kotlin diff --git a/airesources/Kotlin/runGameExecutable.bat b/airesources/Kotlin/runGameExecutable.bat new file mode 100644 index 000000000..2862919d4 --- /dev/null +++ b/airesources/Kotlin/runGameExecutable.bat @@ -0,0 +1,5 @@ +kotlinc.bat *.kt -include-runtime -d mybot.jar +jar ufe mybot.jar MyBotKt +kotlinc.bat *.kt -include-runtime -d randombot.jar +jar ufe randombot.jar RandomBotKt +.\halite.exe -d "30 30" "java -jar mybot.jar" "java -jar randombot.jar" diff --git a/airesources/Kotlin/runGameExecutable.sh b/airesources/Kotlin/runGameExecutable.sh new file mode 100644 index 000000000..b3f96f326 --- /dev/null +++ b/airesources/Kotlin/runGameExecutable.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +kotlinc *.kt -include-runtime -d mybot.jar +jar ufe mybot.jar MyBotKt +kotlinc *.kt -include-runtime -d randombot.jar +jar ufe randombot.jar RandomBotKt +./halite -d "30 30" "java -jar mybot.jar" "java -jar randombot.jar"