about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEmile <git@emile.space>2023-04-09 00:37:54 +0200
committerEmile <git@emile.space>2023-04-09 00:37:54 +0200
commit87142c0cb5f42d877327c357497a5be6f3c5dbd0 (patch)
treee4b2094315dc16fe680ad0a15587bb0671dea636
parent907f5bc763959c3cc2196329a600a8afedebac5a (diff)
Should work, lol
-rw-r--r--README.md46
-rw-r--r--go.mod10
-rw-r--r--go.sum25
-rw-r--r--main.go (renamed from src/init.go)235
-rw-r--r--src/cmd.go20
-rw-r--r--src/config.go76
-rw-r--r--src/logic.go17
-rw-r--r--src/main.go27
-rw-r--r--src/run.go84
-rw-r--r--src/structs.go49
10 files changed, 257 insertions, 332 deletions
diff --git a/README.md b/README.md
index e2887cb..c473557 100644
--- a/README.md
+++ b/README.md
@@ -1,43 +1,11 @@
-## r2wars
+# r2wars-new
 
-The goal of r2wars is to place two bots in as shared memory space and let
-them battle against each other until one of them cannot run anymore, because
-of some kind of broken instruction.
+This is a quick and dirty implementation of r2wars for the easterhegg 20
+workshops I'm giving (It's currently 01:00 of the day of the workshop and I'm
+realizing that the code I wrote about 3 years ago is kind of broken).
 
-A more informal README can be found
-[here](https://github.com/radareorg/radare2-extras/tree/master/r2wars).
-
-## Usage
-
-You'll probably first of all want to simply play with the two provided bots. In
-order to do so, run the game like this:
-
-```go
-go run ./... -t 1s -v ./bots/warrior0.asm ./bots/warrior1.asm
 ```
-
-This runs the game with a round duration of 1 second and an info verbosity
-level using the two provided bots. You can attach more bots if you'd like,
-each bot increases the arena size by 512 bytes by default.
-
-You can tweak most of the settings as displayed in the help:
-
-```go
-$ go run ./... -h
-Usage of src:
-  -arch string
-    	bot architecture (mips|arm|x86) (default "x86")
-  -bits int
-    	bot bitness (8|16|32|64) (default 32)
-  -maxProgSize int
-    	the maximum bot size (default 64)
-  -memPerBot int
-    	the amount of memory each bot should add to the arena (default 512)
-  -t duration
-    	The duration of a round (default 250ns)
-  -v	info
-  -vv
-    	debug
-  -vvv
-    	trace
+; CGO_ENABLED=0 go run ./... -t 1s -v ./bots/warrior0.asm ./bots/warrior1.as
 ```
+
+#worksonmymachine
diff --git a/go.mod b/go.mod
index 170fcbc..e344fca 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,9 @@
-module git.darknebu.la/emile/genetic_r2_bots
+module github.com/hanemile/r2wars
 
-go 1.13
+go 1.19
 
 require (
-	github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a
-	github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1 // indirect
-	github.com/sirupsen/logrus v1.4.2
+	github.com/radareorg/r2pipe-go v0.2.1 // indirect
+	github.com/sirupsen/logrus v1.9.0 // indirect
+	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
 )
diff --git a/go.sum b/go.sum
index ecc0ad3..0d37478 100644
--- a/go.sum
+++ b/go.sum
@@ -1,16 +1,13 @@
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a h1:enQJXC+C+uCM0rpONspYMD6+Jf6eYNj4gCD4MIXkP8c=
-github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a/go.mod h1:xnSZtTv/jeHkBsW7Mg6lJWB8Ke17mg3dMCMRwI16LnM=
-github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1 h1:XZlja+DeIOJeEPWAfM9M5wko0keB9qgRfuuWbry6VBQ=
-github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1/go.mod h1:lh74SQgfeEuNq74dKWzDLuVB+/ntX5c4g1oDyL4GkGg=
-github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+github.com/radareorg/r2pipe-go v0.2.1 h1:2bVIi7qHPQCdjjngcJbQO2VHSqPaRBt5LUAMk2uq84o=
+github.com/radareorg/r2pipe-go v0.2.1/go.mod h1:HNUWNjS7SjzhZ7McDLhvIBSOLz1X9DNLjj4J52pAj3Y=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/src/init.go b/main.go
index ee6db87..abaf5fa 100644
--- a/src/init.go
+++ b/main.go
@@ -1,15 +1,141 @@
 package main
 
 import (
+	"flag"
 	"fmt"
 	"math/rand"
+	"os"
 	"strings"
 	"time"
 
-	r2pipe "github.com/radare/r2pipe-go"
+	"github.com/radareorg/r2pipe-go"
 	"github.com/sirupsen/logrus"
 )
 
+// Config defines the meta config
+type Config struct {
+
+	// Arch defines the architecture the battle should run in
+	Arch string
+
+	// Bits defines the bitness
+	Bits int
+
+	// Memsize defines the arena size
+	Memsize int
+
+	// MaxProgSize defines the maximal bot size
+	MaxProgSize int
+
+	// Bots defines a list of bots to take part in the battle
+	Bots []Bot
+
+	// AmountOfBots defines the amount of bots taking part in the tournament
+	AmountOfBots int
+
+	// RandomOffsets defines the offset in memory where the bots should be placed
+	RandomOffsets []int
+
+	// GameRoundTime defines the length of a gameround
+	GameRoundDuration time.Duration
+}
+
+// Bot defines a bot
+type Bot struct {
+
+	// Path defines the path to the source of the bot
+	Path string
+
+	// Source defines the source of the bot after being compiled with rasm2
+	Source string
+
+	// Addr defines the initial address the bot is placed at
+	Addr int
+
+	// Regs defines the state of the registers of the bot
+	// It is used to store the registers after each round and restore them in the
+	// next round when the bot's turn has come
+	Regs string
+}
+
+func parseConfig() Config {
+	arch := flag.String("arch", "x86", "bot architecture (mips|arm|x86)")
+	bits := flag.Int("bits", 32, "bot bitness (8|16|32|64)")
+	maxProgSize := flag.Int("maxProgSize", 64, "the maximum bot size")
+	memPerBot := flag.Int("memPerBot", 512, "the amount of memory each bot should add to the arena")
+	gameRoundDuration := flag.Duration("t", 250*time.Millisecond, "The duration of a round")
+
+	v := flag.Bool("v", false, "info")
+	vv := flag.Bool("vv", false, "debug")
+	vvv := flag.Bool("vvv", false, "trace")
+
+	flag.Parse()
+
+	if *v == true {
+		logrus.SetLevel(logrus.InfoLevel)
+	} else if *vv == true {
+		logrus.SetLevel(logrus.DebugLevel)
+	} else if *vvv == true {
+		logrus.SetLevel(logrus.TraceLevel)
+	} else {
+		logrus.SetLevel(logrus.WarnLevel)
+	}
+
+	// parse all trailing command line arguments as path to bot sourcecode
+	amountOfBots := flag.NArg()
+
+	memsize := amountOfBots * *memPerBot
+
+	logrus.WithFields(logrus.Fields{
+		"mem per bot":  *memPerBot,
+		"amountOfBots": amountOfBots,
+		"memsize":      memsize,
+	}).Infof("Loaded config")
+
+	// define a config to return
+	config := Config{
+		Arch:              *arch,
+		Bits:              *bits,
+		Memsize:           memsize,
+		MaxProgSize:       *maxProgSize,
+		AmountOfBots:      amountOfBots,
+		GameRoundDuration: *gameRoundDuration,
+	}
+
+	return config
+}
+
+// define bots defines the bots given via command line arguments
+func defineBots(config *Config) {
+
+	logrus.Info("Defining the bots")
+
+	// define a list of bots by parsing the command line arguments one by one
+	var bots []Bot
+	for i := 0; i < config.AmountOfBots; i++ {
+		bot := Bot{
+			Path: flag.Arg(i),
+		}
+		bots = append(bots, bot)
+	}
+
+	config.Bots = bots
+}
+
+func r2cmd(r2p *r2pipe.Pipe, input string) string {
+
+	logrus.Tracef("> %s", input)
+
+	// send a command
+	buf1, err := r2p.Cmd(input)
+	if err != nil {
+		panic(err)
+	}
+
+	// return the result of the command as a string
+	return buf1
+}
+
 func buildBots(config *Config) {
 
 	logrus.Info("Building all bots")
@@ -228,3 +354,110 @@ func defineErrors(r2p *r2pipe.Pipe) {
 	_ = r2cmd(r2p, "e cmd.esil.ioer=f theend=1")
 	_ = r2cmd(r2p, "f theend=0")
 }
+
+// StepIn steps in and stores the state of the registers for the given bot
+func stepIn(r2p *r2pipe.Pipe) {
+	_ = r2cmd(r2p, "aes")
+}
+
+// switchPlayer returns the id of the next Player
+func switchPlayer(r2p *r2pipe.Pipe, currentPlayer int, config *Config) int {
+
+	// calculate the index of the nextPlayer
+	nextPlayer := (currentPlayer + 1) % config.AmountOfBots
+
+	return nextPlayer
+}
+
+func arena(r2p *r2pipe.Pipe, config *Config, id, gen int) string {
+	var res string = ""
+
+	// clear the screen
+	res += "\x1b[2J\x1b[0;0H"
+	// res += fmt.Sprintf("%s\n", r2cmd(r2p, "?eg 0 0"))
+
+	// print some general information such as the current user and the round the
+	// game is in
+	ip := fmt.Sprintf("%s\n", r2cmd(r2p, "aer~eip"))
+	res += fmt.Sprintf("Round: %d \t\t User: %d \t\t ip: %s\n", gen, id, ip)
+
+	// print the memory space
+	res += fmt.Sprintf("%s\n", r2cmd(r2p, "pxa 0x400 @ 0"))
+	// res += fmt.Sprintf("%s\n", r2cmd(r2p, fmt.Sprintf("pd 0x10 @ %d", config.Bots[id].Addr)))
+
+	// res += fmt.Sprintf("%s\n", r2cmd(r2p, "prc 0x200 @ 0"))
+
+	return res
+}
+
+// runGame actually runs the game (surprise!)
+func runGame(r2p *r2pipe.Pipe, config *Config) {
+
+	// start the competition
+	var botid int = 0
+	var round int = 0
+	for true {
+
+		// load the registers
+		r2cmd(r2p, config.Bots[botid].Regs)
+
+		// Step
+		stepIn(r2p)
+
+		// store the regisers
+		registers := r2cmd(r2p, "aerR")
+		registersStripped := strings.Replace(registers, "\n", ";", -1)
+		config.Bots[botid].Regs = registersStripped
+
+		logrus.Info(arena(r2p, config, botid, round))
+
+		if dead(r2p, botid) == true {
+			logrus.Warnf("DEAD (round %d)", round)
+			os.Exit(1)
+		}
+
+		// switch players, if the new botid is 0, a new round has begun
+		botid = switchPlayer(r2p, botid, config)
+		if botid == 0 {
+			round++
+		}
+
+		// sleep only a partial of the total round time, as a round is made up of
+		// the movements of multiple bots
+		time.Sleep(config.GameRoundDuration / time.Duration(config.AmountOfBots))
+	}
+}
+
+func dead(r2p *r2pipe.Pipe, botid int) bool {
+	status := r2cmd(r2p, "?v 1+theend")
+
+	if status != "" && status != "0x1" {
+		logrus.Warn("[!] Bot %d has died", botid)
+		return true
+	}
+	return false
+}
+
+func main() {
+	fmt.Println("hi")
+
+	config := parseConfig()
+	defineBots(&config)
+	buildBots(&config)
+	genRandomOffsets(&config)
+
+	// initialize the arena (allocate memory + initialize the ESIL VM & stack)
+	r2p := initArena(&config)
+
+	// place the bots in the arena
+	placeBots(r2p, &config)
+
+	// if an error occurs (interrupt, ioerror, trap, ...), the ESIL VM should set
+	// a flag that can be used to determine if a player has died
+	defineErrors(r2p)
+
+	// run the actual game
+	runGame(r2p, &config)
+
+	r2p.Close()
+}
diff --git a/src/cmd.go b/src/cmd.go
deleted file mode 100644
index a17da4a..0000000
--- a/src/cmd.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package main
-
-import (
-	"github.com/radare/r2pipe-go"
-	"github.com/sirupsen/logrus"
-)
-
-func r2cmd(r2p *r2pipe.Pipe, input string) string {
-
-	logrus.Tracef("> %s", input)
-
-	// send a command
-	buf1, err := r2p.Cmd(input)
-	if err != nil {
-		panic(err)
-	}
-
-	// return the result of the command as a string
-	return buf1
-}
diff --git a/src/config.go b/src/config.go
deleted file mode 100644
index 706d29e..0000000
--- a/src/config.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package main
-
-import (
-	"flag"
-	"time"
-
-	"github.com/sirupsen/logrus"
-)
-
-// parseConfig parses the config needed to start the game
-func parseConfig() Config {
-
-	// bot configs
-	arch := flag.String("arch", "x86", "bot architecture (mips|arm|x86)")
-	bits := flag.Int("bits", 32, "bot bitness (8|16|32|64)")
-	maxProgSize := flag.Int("maxProgSize", 64, "the maximum bot size")
-	memPerBot := flag.Int("memPerBot", 512, "the amount of memory each bot should add to the arena")
-	gameRoundDuration := flag.Duration("t", 250*time.Millisecond, "The duration of a round")
-
-	v := flag.Bool("v", false, "info")
-	vv := flag.Bool("vv", false, "debug")
-	vvv := flag.Bool("vvv", false, "trace")
-
-	// parse the flags
-	flag.Parse()
-
-	if *v == true {
-		logrus.SetLevel(logrus.InfoLevel)
-	} else if *vv == true {
-		logrus.SetLevel(logrus.DebugLevel)
-	} else if *vvv == true {
-		logrus.SetLevel(logrus.TraceLevel)
-	} else {
-		logrus.SetLevel(logrus.WarnLevel)
-	}
-
-	// parse all trailing command line arguments as path to bot sourcecode
-	amountOfBots := flag.NArg()
-
-	memsize := amountOfBots * *memPerBot
-
-	logrus.WithFields(logrus.Fields{
-		"mem per bot":  *memPerBot,
-		"amountOfBots": amountOfBots,
-		"memsize":      memsize,
-	}).Infof("Loaded config")
-
-	// define a config to return
-	config := Config{
-		Arch:              *arch,
-		Bits:              *bits,
-		Memsize:           memsize,
-		MaxProgSize:       *maxProgSize,
-		AmountOfBots:      amountOfBots,
-		GameRoundDuration: *gameRoundDuration,
-	}
-
-	return config
-}
-
-// define bots defines the bots given via command line arguments
-func defineBots(config *Config) {
-
-	logrus.Info("Defining the bots")
-
-	// define a list of bots by parsing the command line arguments one by one
-	var bots []Bot
-	for i := 0; i < config.AmountOfBots; i++ {
-		bot := Bot{
-			Path: flag.Arg(i),
-		}
-		bots = append(bots, bot)
-	}
-
-	config.Bots = bots
-}
diff --git a/src/logic.go b/src/logic.go
deleted file mode 100644
index 5bc6461..0000000
--- a/src/logic.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package main
-
-import (
-	"log"
-
-	"github.com/radare/r2pipe-go"
-)
-
-func dead(r2p *r2pipe.Pipe, botid int) bool {
-	status := r2cmd(r2p, "?v 1+theend")
-
-	if status != "" && status != "0x1" {
-		log.Printf("[!] Bot %d has died", botid)
-		return true
-	}
-	return false
-}
diff --git a/src/main.go b/src/main.go
deleted file mode 100644
index d5e0107..0000000
--- a/src/main.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package main
-
-func main() {
-
-	// initialize the game by parsing the config, defining the bots, building the
-	// bots and generating random offsets where the bots should be placed in
-	// memory
-	config := parseConfig()
-	defineBots(&config)
-	buildBots(&config)
-	genRandomOffsets(&config)
-
-	// initialize the arena (allocate memory + initialize the ESIL VM & stack)
-	r2p := initArena(&config)
-
-	// place the bots in the arena
-	placeBots(r2p, &config)
-
-	// if an error occurs (interrupt, ioerror, trap, ...), the ESIL VM should set
-	// a flag that can be used to determine if a player has died
-	defineErrors(r2p)
-
-	// run the actual game
-	runGame(r2p, &config)
-
-	r2p.Close()
-}
diff --git a/src/run.go b/src/run.go
deleted file mode 100644
index fb3c249..0000000
--- a/src/run.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"os"
-	"strings"
-	"time"
-
-	"github.com/radare/r2pipe-go"
-	"github.com/sirupsen/logrus"
-)
-
-// StepIn steps in and stores the state of the registers for the given bot
-func stepIn(r2p *r2pipe.Pipe) {
-	_ = r2cmd(r2p, "aes")
-}
-
-// switchPlayer returns the id of the next Player
-func switchPlayer(r2p *r2pipe.Pipe, currentPlayer int, config *Config) int {
-
-	// calculate the index of the nextPlayer
-	nextPlayer := (currentPlayer + 1) % config.AmountOfBots
-
-	return nextPlayer
-}
-
-func arena(r2p *r2pipe.Pipe, config *Config, id, gen int) string {
-	var res string = ""
-
-	// clear the screen
-	res += "\x1b[2J\x1b[0;0H"
-	// res += fmt.Sprintf("%s\n", r2cmd(r2p, "?eg 0 0"))
-
-	// print some general information such as the current user and the round the
-	// game is in
-	ip := fmt.Sprintf("%s\n", r2cmd(r2p, "aer~eip"))
-	res += fmt.Sprintf("Round: %d \t\t User: %d \t\t ip: %s\n", gen, id, ip)
-
-	// print the memory space
-	res += fmt.Sprintf("%s\n", r2cmd(r2p, "pxa 0x400 @ 0"))
-	// res += fmt.Sprintf("%s\n", r2cmd(r2p, fmt.Sprintf("pd 0x10 @ %d", config.Bots[id].Addr)))
-
-	// res += fmt.Sprintf("%s\n", r2cmd(r2p, "prc 0x200 @ 0"))
-
-	return res
-}
-
-// runGame actually runs the game (surprise!)
-func runGame(r2p *r2pipe.Pipe, config *Config) {
-
-	// start the competition
-	var botid int = 0
-	var round int = 0
-	for true {
-
-		// load the registers
-		r2cmd(r2p, config.Bots[botid].Regs)
-
-		// Step
-		stepIn(r2p)
-
-		// store the regisers
-		registers := r2cmd(r2p, "aerR")
-		registersStripped := strings.Replace(registers, "\n", ";", -1)
-		config.Bots[botid].Regs = registersStripped
-
-		logrus.Info(arena(r2p, config, botid, round))
-
-		if dead(r2p, botid) == true {
-			logrus.Warnf("DEAD (round %d)", round)
-			os.Exit(1)
-		}
-
-		// switch players, if the new botid is 0, a new round has begun
-		botid = switchPlayer(r2p, botid, config)
-		if botid == 0 {
-			round++
-		}
-
-		// sleep only a partial of the total round time, as a round is made up of
-		// the movements of multiple bots
-		time.Sleep(config.GameRoundDuration / time.Duration(config.AmountOfBots))
-	}
-}
diff --git a/src/structs.go b/src/structs.go
deleted file mode 100644
index c0cddc2..0000000
--- a/src/structs.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package main
-
-import "time"
-
-// Config defines the meta config
-type Config struct {
-
-	// Arch defines the architecture the battle should run in
-	Arch string
-
-	// Bits defines the bitness
-	Bits int
-
-	// Memsize defines the arena size
-	Memsize int
-
-	// MaxProgSize defines the maximal bot size
-	MaxProgSize int
-
-	// Bots defines a list of bots to take part in the battle
-	Bots []Bot
-
-	// AmountOfBots defines the amount of bots taking part in the tournament
-	AmountOfBots int
-
-	// RandomOffsets defines the offset in memory where the bots should be placed
-	RandomOffsets []int
-
-	// GameRoundTime defines the length of a gameround
-	GameRoundDuration time.Duration
-}
-
-// Bot defines a bot
-type Bot struct {
-
-	// Path defines the path to the source of the bot
-	Path string
-
-	// Source defines the source of the bot after being compiled with rasm2
-	Source string
-
-	// Addr defines the initial address the bot is placed at
-	Addr int
-
-	// Regs defines the state of the registers of the bot
-	// It is used to store the registers after each round and restore them in the
-	// next round when the bot's turn has come
-	Regs string
-}