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"