GithubHelp home page GithubHelp logo

lux-ai-challenge / lux-design-s1 Goto Github PK

View Code? Open in Web Editor NEW
898.0 12.0 153.0 17.26 MB

Home to the design and engine of the @Lux-AI-Challenge Season 1, hosted on @kaggle

Home Page: https://lux-ai.org/

License: Apache License 2.0

TypeScript 3.89% JavaScript 1.42% C++ 36.74% Java 0.35% Python 0.88% Shell 0.18% Batchfile 0.01% PowerShell 0.07% Dockerfile 0.04% Jupyter Notebook 54.66% Kotlin 0.36% Rust 1.37% Makefile 0.04%
ai competition programming lux-ai hacktoberfest reinforcement-learning

lux-design-s1's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lux-design-s1's Issues

validateCommand() function is hiding at least a few bugs

As I originally tried to make sense of the validateCommand() function, I noticed a couple inconsistencies, which at the time I did not know were bugs or not. Separating the error check from the throwing of the warning in that function would improve readability greatly and would make making changes much easier.

sample_replay.json is a previous version

I would like to use the default viewer https://2021vis.lux-ai.org/

to view the sample_replay.json

But I get this message:

Screenshot 2021-07-05 5 45 04 PM

When I try to manually build the previous version of the viewer I get the messages mentioned in this issue Install/setup dev questions

Here is another example:

root@docker-ubuntu-s-1vcpu-2gb-nyc1-01:~/ap/viewer-ver1/LuxViewer2021-1.0.0# npm i -g serve
/root/ap/emsdk/node/14.15.5_64bit/bin/serve -> /root/ap/emsdk/node/14.15.5_64bit/lib/node_modules/serve/bin/serve.js
+ serve@12.0.0
updated 1 package in 4.665s
root@docker-ubuntu-s-1vcpu-2gb-nyc1-01:~/ap/viewer-ver1/LuxViewer2021-1.0.0# serve dist
ERROR: Cannot copy to clipboard: Both xsel and fallback failed

   ┌───────────────────────────────────┐
   │                                   │
   │   Serving!                        │
   │                                   │
   │   Local:  http://localhost:5000   │
   │                                   │
   └───────────────────────────────────┘

^C
INFO: Gracefully shutting down. Please wait...
root@docker-ubuntu-s-1vcpu-2gb-nyc1-01:~/ap/viewer-ver1/LuxViewer2021-1.0.0# cp -r assets/ dist
root@docker-ubuntu-s-1vcpu-2gb-nyc1-01:~/ap/viewer-ver1/LuxViewer2021-1.0.0# serve dist
root@docker-ubuntu-s-1vcpu-2gb-nyc1-01:~/ap/viewer-ver1/LuxViewer2021-1.0.0# npm run dev

> lux-viewer-2021@1.0.0 dev /root/ap/viewer-ver1/LuxViewer2021-1.0.0
> webpack --mode development && webpack-dev-server --mode development --devtool source-map

sh: 1: webpack: not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! lux-viewer-2021@1.0.0 dev: `webpack --mode development && webpack-dev-server --mode development --devtool source-map`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the lux-viewer-2021@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-07-05T21_41_41_040Z-debug.log

Game Balancing

Parameter changes

Considering some penalties e.g. city expansion penalties

stateful replays

add CLI option to run matches that then create stateful replays or convert action based replays for e.g. easier analysis

CityTile road fix

As most recently mentioned by snozzled, the game state is generated with cell.road instead of cell.getRoad(), so the hardcoded exception for CityTiles is skipped. This is not an issue with the gameplay since the engine still uses cell.getRoad().

Position.direction_to() should return all directions which are shortest path

Currently, Position.direction_to(target_pos: Position) -> DIRECTIONS will return only a single direction. However, most of the time there are two possible directions for the shortest path. For implementing a move optimizer it is important to know all possible shortest path directions as there are usually 2 (unless some coordinate is identical).

Therefore, I suggest to implement the function as Position.direction_to(target_pos: Position) -> Set[DIRECTION] which returns a set of all directions in order to most quickly reach the destination.

For example Position(1,1).direction_to(Position(2,2)) -> {"s", "e"}

Design Improvements

Thanks to a member from the community!

Lux_AI_Challance_-_Improvements.pdf

Sticking this here just to keep it alive and tracked on github.

The main thing I think that actually should be done is regrowth for wood given that wood is used for city building.

The other thing is either making research passive (since you always want to research if you aren't building units) or making research have a higher opportunity cost in relation to the number of units you can build.

Fix cooldown mechanics

Cooldown always goes down by 1 each turn

Cooldown increases by a base amount depending on unit. Increases less if tile unit is currently on is developed (has roads).

Consider giving workers a base cooldown of 2.

Memory leak in cpp kit

I think there are big memory leaks in cpp kit
here
void resetPlayerStates ()
{
...
players[0].cities.clear ();
...
}

cities is std::map<std::string, City *>
each turn we make new allocation
this->players[team].cities[cityid] = new lux::City (team, cityid, fuel, lightUpkeep);
but we never do smth like
delete players[team].cities[cityid];
(clear () doesn't do it for dynamic memory)

the same problem with std::vector<CityTile *> citytiles;

because of this, sometimes an error occurs in long games
RuntimeError: abort(RuntimeError: abort(Cannot enlarge memory arrays to size 16781312 bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value 16777216, (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ) at Error

I removed these pointers locally and this solved the problem.
...

  • std::vector<CityTile *> citytiles;
  • std::vector citytiles;
    ...
  • std::map<std::string, City *> cities;
  • std::map<std::string, City> cities;
    ...
    Why were they needed?

Check it, please

Map generation sometimes fails

TypeError: Cannot read property 'hasResource' of undefined
    at Object.generateGame (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/Game/gen.js:151:37)
    at Function.<anonymous> (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:87:38)
    at step (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:33:23)
    at Object.next (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:14:53)
    at /opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:4:12)
    at Function.LuxDesignLogic.initialize (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/logic.js:60:16)
    at LuxDesign.<anonymous> (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/design.js:67:62)
    at step (/opt/homebrew/lib/node_modules/@lux-ai/2021-challenge/lib/es5/design.js:48:23)
    

Can't directly run cpp files in lux-ai-2021 (ETXTBSY error)

So I've heard, you can run cpp files directly into lux-ai-2021. However, when I try to run it with my own bot, I get this error. https://pastebin.com/CQDev0Kw error in its entirety.

diego@adhoc:~/Desktop/LuxBot$ sudo lux-ai-2021 src/main.cpp src/main.cpp 

-=-=-=-=-=-=-=-=-=-=-=-| [INFO] match_QiUDBKVEPU7A |-=-=-=-=-=-=-=-=-=-=-=-
[INFO] (match_QiUDBKVEPU7A) - Design: lux_ai_2021 | Initializing match - ID: QiUDBKVEPU7A, Name: match_QiUDBKVEPU7A
Error: spawn ETXTBSY
    at ChildProcess.spawn (internal/child_process.js:403:11)
    at spawn (child_process.js:580:9)
    at Object.spawnWithSignal [as spawn] (child_process.js:717:17)
    at Object.spawn [as default] (/usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/cross-spawn/index.js:12:24)
    at /usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/dimensions-ai/lib/main/Agent/index.js:653:46
    at new Promise (<anonymous>)
    at Agent._spawnProcess (/usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/dimensions-ai/lib/main/Agent/index.js:646:16)
    at Agent.<anonymous> (/usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/dimensions-ai/lib/main/Agent/index.js:628:56)
    at step (/usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/dimensions-ai/lib/main/Agent/index.js:46:23)
    at Object.next (/usr/local/lib/node_modules/@lux-ai/2021-challenge/node_modules/dimensions-ai/lib/main/Agent/index.js:27:53) {
  errno: -26,
  code: 'ETXTBSY',
  syscall: 'spawn'
}

I get this error when trying to run the v1.1.x branch of the cpp kit as well; Not sure what is causing it. It works fine when transpiled into JS. I've tried running the lux-ai-2021 command as sudo and not sudo, though it doesn't make a difference. Here's the exact main.cpp code I tried to run in simple/:

#include "lux/kit.hpp"
#include "lux/define.cpp"
#include <string.h>
#include <vector>
#include <set>
#include <stdio.h>

using namespace std;
using namespace lux;
int main()
{
  kit::Agent gameState = kit::Agent();
  gameState.initialize();

  while (true)
  {
    gameState.update();

    vector<string> actions = vector<string>();
    Player player = gameState.players[gameState.id];
    Player opponent = gameState.players[(gameState.id + 1) % 2];

    GameMap gameMap = gameState.map;

    vector<Cell *> resourceTiles = vector<Cell *>();
    for (int y = 0; y < gameMap.height; y++)
    {
      for (int x = 0; x < gameMap.width; x++)
      {
        Cell *cell = gameMap.getCell(x, y);
        if (cell->hasResource())
        {
          resourceTiles.push_back(cell);
        }
      }
    }

    int citiesToBuild = 0;
    for (auto it : player.cities)
    {
      City *city = it.second;
      if (city->fuel > city->getLightUpkeep() * (int) GAME_CONSTANTS["PARAMETERS"]["NIGHT_LENGTH"] + 1000)
      {
        citiesToBuild += 1;
      }
      for (auto citytile : city->citytiles)
      {
        if (citytile->canAct()) {
          // you can use the following to get the citytile to research or build a worker
          // actions.push_back(citytile.research());
          // actions.push_back(citytile.buildWorker());
        }
      }
    }

    for (int i = 0; i < player.units.size(); i++)
    {
      Unit unit = player.units[i];
      if (unit.isWorker() && unit.canAct())
      {
        if (unit.getCargoSpaceLeft() > 0)
        {
          // if the unit is a worker and we have space in cargo, lets find the nearest resource tile and try to mine it
          Cell *closestResourceTile;
          float closestDist = 9999999;
          for (auto it = resourceTiles.begin(); it != resourceTiles.end(); it++)
          {
            auto cell = *it;
            if (cell->resource.type == ResourceType::coal && !player.researchedCoal()) continue;
            if (cell->resource.type == ResourceType::uranium && !player.researchedUranium()) continue;
            float dist = cell->pos.distanceTo(unit.pos);
            if (dist < closestDist)
            {
              closestDist = dist;
              closestResourceTile = cell;
            }
          }
          if (closestResourceTile != nullptr)
          {
            auto dir = unit.pos.directionTo(closestResourceTile->pos);
            actions.push_back(unit.move(dir));
          }
        }
        else
        {
          if (player.cities.size() > 0)
          {
            auto city_iter = player.cities.begin();
            auto city = city_iter->second;

            float closestDist = 999999;
            CityTile *closestCityTile;
            for (auto citytile : city->citytiles)
            {
              float dist = citytile->pos.distanceTo(unit.pos);
              if (dist < closestDist)
              {
                closestCityTile = citytile;
                closestDist = dist;
              }
            }
            if (closestCityTile != nullptr)
            {
              auto dir = unit.pos.directionTo(closestCityTile->pos);

              if (citiesToBuild > 0 && unit.pos.isAdjacent(closestCityTile->pos) && unit.canBuild(gameMap))
              {
                actions.push_back(unit.buildCity());
              }
              else
              {
                actions.push_back(unit.move(dir));
              }
            }
          }
        }
      }
    }

    for (int i = 0; i < actions.size(); i++)
    {
      if (i != 0)
        cout << ",";
      cout << actions[i];
    }
    cout << endl;
    gameState.end_turn();
  }
  return 0;
}

One off errors

There is a one off error either in the engine, kit, or visualizer.

E.g. visualizer shows the first turn as turn 0 and actually renders the end of the turn 0.
Kits are 1-indexed (due to engine starting at turn 1).

Multiple redefinition of internal lux/ files when importing a header / cpp file combo

Bug: Multiple redefinition of internal lux/ files when importing a header / cpp file combo that both contain lux/kit.hpp.

Minimum possible example from simple/ in kits/cpp

main.cpp

  #include "lux/kit.hpp"
  #include "foo.h"
  #include <string.h>
  #include <vector>
  #include <set>
  #include <stdio.h>
  
  using namespace std;
  using namespace lux;
  int main()
...

foo.h

  #ifndef FOO_H
  #define FOO_H 
  #include "lux/kit.hpp"
  void foo();
  #endif

foo.cpp

  #include "lux/kit.hpp"
  #include "foo.h"

  void foo() {
    int i = 1 + 1;
  }

Compile command: emcc -s FORCE_FILESYSTEM=1 --pre-js internals/init_fs.js main.cpp foo.cpp -o main.js

Error: https://pastebin.com/5G0Garja

Note: Manually adding header guards to each file in lux , specifically kit.hpp, alleviated most errors. This change has a pull request already. The remaining errors after this change are here: https://pastebin.com/YMJXAFDC

Note 2: This would've thrown an error anyway if you didn't mess with main.js. In fact, this is inherently a C++ problem because if you run g++ main.cpp foo.cpp you get the same error

Possible solution: It's possible to simply move all static variable definitions into a .cpp file in /lux, then put that .cpp file in the compile command and it works just fine as there is now only one definition of those static variables

Spec updates

  • Clarify that citytiles can do one action a turn
  • Refer to road level as a road level in code, not cell cooldown
  • Clarify what collection rate means (eg its resources / turn, not turns/resource)
  • Clarify that transferring resources will transfer as much as possible to worker, then return the remaining to original unit
  • Maybe clarify that actions are simultaneously applied to the current state.
  • Fix typo with cart road building. cart auto adds 0.5 to the road level of the cell they start on each turn. (not where they end up)

Allow users to supress certain warnings

Some users see the collision warnings as being too verbose

One option here is instead of setting the suppress argument to true, set it to a list of warnings to suppress

Cannot ctrl-c on windows

the cli tool doesn't let you ctrl-c in the middle.

the cli tool should 1. let you ctrl-c and 2. auto close after a match runs.

Fatal memory overflow in specific seeds in C++

I don't know how to explain this. I've literally debugged this for days, even rewrote my multi-file project into a one-file one, and I am still not sure what causes it. I am on Linux, and program in the C++ v1.1.x kit.

Basically, there are certain seeds that cause my bot to crash in one gigantic memory overflow, which is always near turn 340-360. The error always looks like this, though memory access out of bounds can also happen:

[Agent 0 Log] Cannot enlarge memory arrays to size 16781312 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 
[Agent 0 Log] exception thrown: RuntimeError: abort(Cannot enlarge memory arrays to size 16781312 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ) at Error
[Agent 0 Log]     at jsStackTrace (/home/diego/Desktop/LuxBot/main.js:1807:19)
[Agent 0 Log]     at stackTrace (/home/diego/Desktop/LuxBot/main.js:1824:16)
[Agent 0 Log]     at abort (/home/diego/Desktop/LuxBot/main.js:1543:44)
[Agent 0 Log]     at abortOnCannotGrowMemory (/home/diego/Desktop/LuxBot/main.js:1931:7)
[Agent 0 Log]     at _emscripten_resize_heap (/home/diego/Desktop/LuxBot/main.js:1936:7)
[Agent 0 Log]     at <anonymous>:wasm-function[3226]:0x60e6e
[Agent 0 Log]     at malloc (<anonymous>:wasm-function[3220]:0x5edc8)
[Agent 0 Log]     at <anonymous>:wasm-function[3002]:0x5acdc
[Agent 0 Log]     at <anonymous>:wasm-function[102]:0x6b50
[Agent 0 Log]     at <anonymous>:wasm-function[57]:0x41ba,RuntimeError: abort(Cannot enlarge memory arrays to size 16781312 bytes (OOM). Either (1) compile with  -s INITIAL_MEMORY=X  with X higher than the current value 16777216, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ) at Error

Keep in mind that this only happens rarely, like 1 in 50 seeds.

Here is a one file version of my bot using the cpp kit in the v1.1.x branch:

#include "lux/kit.hpp"
#include "lux/define.cpp"
#include <string.h>
#include <vector>
#include <set>
#include <stdio.h>
#include <map>

using namespace std;
using namespace lux;
int main()
{
	kit::Agent gameState;
	gameState.initialize();

	while (true)
	{
		GameMap& gameMap = gameState.map;
		Player& player = gameState.players[gameState.id];
		vector<string> actions;
		gameState.update();

		vector<Cell*> resourceTiles;
		for (int y = 0; y < gameMap.height; y++)
		{
			for (int x = 0; x < gameMap.width; x++)
			{
				Cell *cell = gameMap.getCell(x, y);
				if (cell->hasResource())
				{
					resourceTiles.push_back(cell);
				}
			}
		}

		for (int i = 0; i < player.units.size(); i++)
		{
			Unit& unit = player.units[i];
			if(unit.isWorker() && unit.canAct()) {
				
				if(unit.getCargoSpaceLeft() != 0) {
					ResourceType resourceToFind = ResourceType::wood;

					if(player.researchedCoal()) resourceToFind = ResourceType::coal;
					if(player.researchedUranium()) resourceToFind = ResourceType::uranium;

					Cell* closestResourceTile = nullptr;
					float closestDist = 999999;

					for(auto it = resourceTiles.begin(); it != resourceTiles.end(); it++) {
						Cell* cell = *it;
						float dist = cell->pos.distanceTo(unit.pos);
						if(cell->resource.type == resourceToFind && dist < closestDist) {
							closestDist = dist;
							closestResourceTile = cell;
						}
					}

					DIRECTIONS dir = unit.pos.directionTo(closestResourceTile->pos);
					actions.push_back(unit.move(dir));
				}
				else {
					CityTile* closestCityTile = nullptr;
					float closestDist = 999999;

					for(auto city : player.cities) {
						for(auto cityTile : city.second->citytiles) {
							float dist = cityTile->pos.distanceTo(unit.pos);

							if(dist < closestDist) {
								closestCityTile = cityTile; closestDist = dist;
							}
						}
					}
					DIRECTIONS dir = unit.pos.directionTo(closestCityTile->pos);
					actions.push_back(unit.move(dir));
				}
			}
		}

		for (int i = 0; i < actions.size(); i++)
		{
			if (i != 0)
				cout << ",";
			cout << actions[i];
		}
		cout << endl;
		// end turn
		gameState.end_turn();
	}

	return 0;
}

To get the same error, you must crosscompile main.cpp into a JS file then run the main.js it against itself in seed 556459304 using the v1.1.x cpp kit.

Here are noteworthy findings:

  • You don't get this error if you run the cpp file directly. If you manage to compile cpp as discussed in #71, you never get this type of error.
  • The error seems to indicate the program only has like 16mb of memory.
  • Replay doesn't show anything noteworthy. I spent hours analyzing the last movements of the program before it crashed and nothing seemed wrong.
  • Happens rarely, like 1 in 50 odds
  • The program always, I mean ALWAYS, crashes when you call kit::Agent.update(). Debugging via cerr showed that the entire program run fine with no issues whatsoever right up until kit::Agent.update().

Add text annotation tool

Let user annotate onto the game with text. There are two places. Putting text into the map, syntax then could be

text(x, y, message, fontsize)

There could also be text on the side, syntax could be

sidetext(message)

This would be on the side in a two column thing

Don't `using namespace std;` at global scope in headers

While using namespace std; may have some benefits, it has some downsides too. Therefore the decision whether or not to use the namespace should be left to the person writing the bot. However, when you put using namespace std; in a header at global scope, that means that you make that decision for the user of the library, as they can't remove this statement.

The fix for this would be to move the using namespace std; into the kit namespace, so this

using namespace std;
namespace kit {
    // ...
}

would become this

namespace kit {
    using namespace std;

    // ...
}

This would be a breaking change though, but given that it's quite early in the competition, I think this is acceptable.

Map Generation

Map Generation:

  • Cool stuff
  • making sure there is always sufficient wood nearby
  • make sure it takes 2 or 3 nights before you can start rolling to next stage

Transferring resources is handled sequentially

It looks like unit actions are handled sequentially in an arbitrary order. This might cause some confusing behaviour where actions that might seem valid/reasonable will silently fail.

Eg if I had:

worker_1: 80 wood, 20 coal
worker_2: 20 wood

and I wanted to do two transfers so that worker_1 can go build a city:

worker_1 --> worker_2: 20 coal
worker_2 --> worker_1: 20 wood

this may or may not work, depending on the order of execution. If worker_2 did its transfer first, it would silently fail because worker_1 is at capacity.

Use Python Enum for constants

A suggestion would be to use Python Enum for constants, because they provide some small advantages over plain class constants. For example

from enum import Enum

class DIRECTION(Enum):
    NORTH = "n"
    WEST = "w"
    SOUTH = "s"
    EAST = "e"
    CENTER = "c"

While they can be used similarly as in the previous version, small advantages - apart from being more pythonic - are

>>> list(DIRECTION)                    # possible to iterate; very useful sometimes
[<DIRECTION.NORTH: 'n'>,
 <DIRECTION.WEST: 'w'>,
 <DIRECTION.SOUTH: 's'>,
 <DIRECTION.EAST: 'e'>,
 <DIRECTION.CENTER: 'c'>]

>>> DIRECTION.NORTH.name    # access to readable name for print output
'NORTH'

>>>  DIRECTION.NORTH.value   # access to raw string value, but there shouldn't be a reason, unless you process external output
'n'

Other advantages are that type-checkers like mypy will notice if you accidentally compare them against unrelated strings.
However, note that if for whatever reason you introduce raw strings instead of using the proper class, you will need to access the value with DIRECTION.NORTH.value (for example for if my_direction.value == "n":)

Proper State Serialization + Dynamics Function

At the moment we do not provide a nice way for users to provide state + actions and receive the next state

A few issues:

  • The engine outputs observations that aren't the same as the state serialization (the current state serialization is human readable and verbose whereas the observations are condensed commands.
  • Not easy to feed a state into the engine and reset the state as engine has a few things stored in random places (although everything is at least under match.state)

This issue would mean a somewhat considerable overhaul

One option:

  • Overhaul how observations work. Engine prints to user a long JSON like string and user parses that as usual. This is the state serialization effectively.

Another option with less work

  • Provide a reset function to allow users to reset match with a serialized state or the condensed observations outputted from the engine. The received observations will continue to be the condensed form of the observations

Tutorials

Would be nice to have some tutorial docs written up before the official release on Kaggle that take someone step by step on how to make a simple bot that can keep a single city alive, then keep several cities alive and build more units, then suggest some slightly advanced paths one could take

Open to the community to helping build one of these! (just don't include a tutorial on a too advanced of a bot)

Update Instructions for Submissions

Users have to run tar -czvf out.tar.gz * within the bot folder for submissions to kaggle work.

Might also want to provide scripts instead (that resolve path stuff)

Fix kits with wrong turn indexing

Currently most kits have the first turn indexed at turn 1. visualizer starts at turn 0.
Also means the night time check should be fixed as well.

js transfer() method

The call signature of the js transfer method here doesn't match the docs.

Also, I suppose it could be simplified down to something like this:

  transfer(destUnit, resourceType, amount) {
    let destID = typeof destUnit === "string" ? destUnit : destUnit.id;
    return `t ${this.id} ${destID} ${resourceType} ${amount}`;
  }

I've not actually tested this.

Consider softer limit on city building

Allow it such that you can build a city tile with 100 of any resource.

This makes programming easier, and is a softer limit and people can choose to write code to mine wood only for efficient building and less waste if they want

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.