Merge branch 'config/hell'
This commit is contained in:
commit
a7e7218417
32 changed files with 2121 additions and 52 deletions
|
@ -11,3 +11,6 @@ mozaic = { git = "https://github.com/ajuvercr/MOZAIC" }
|
||||||
tokio = "0.1.22"
|
tokio = "0.1.22"
|
||||||
rand = { version = "0.6.5", default-features = true }
|
rand = { version = "0.6.5", default-features = true }
|
||||||
futures = "0.1.28"
|
futures = "0.1.28"
|
||||||
|
serde = "1.0.100"
|
||||||
|
serde_derive = "1.0.100"
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
24
backend/game.json
Normal file
24
backend/game.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{"planets":[{"ship_count":7,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":7,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":11},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":10},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":10},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":9},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":9},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":8}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":8},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":7},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":1},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":7},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":6},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":10},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":6},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":9},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":5},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":8},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":4},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":3},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":7},{"id":29,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":5},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":3},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":2},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":9}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":6},{"id":29,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":4},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":2},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":1,"turns_remaining":1},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":8},{"id":30,"ship_count":4,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":5},{"id":29,"ship_count":4,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":3},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":2,"turns_remaining":1},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":2,"turns_remaining":1},{"id":31,"ship_count":3,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":10},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":2,"turns_remaining":7},{"id":30,"ship_count":4,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4}]}
|
43
backend/hex.json
Normal file
43
backend/hex.json
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"planets": [
|
||||||
|
{
|
||||||
|
"name": "protos",
|
||||||
|
"x": -6,
|
||||||
|
"y": 0,
|
||||||
|
"owner": 1,
|
||||||
|
"ship_count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "duteros",
|
||||||
|
"x": -3,
|
||||||
|
"y": 5,
|
||||||
|
"ship_count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tritos",
|
||||||
|
"x": 3,
|
||||||
|
"y": 5,
|
||||||
|
"ship_count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tetartos",
|
||||||
|
"x": 6,
|
||||||
|
"y": 0,
|
||||||
|
"owner": 2,
|
||||||
|
"ship_count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pemptos",
|
||||||
|
"x": 3,
|
||||||
|
"y": -5,
|
||||||
|
"ship_count": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extos",
|
||||||
|
"x": -3,
|
||||||
|
"y": -5,
|
||||||
|
"ship_count": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
1
backend/map.json
Normal file
1
backend/map.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,3 +1,7 @@
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
@ -11,32 +15,14 @@ use mozaic::errors;
|
||||||
|
|
||||||
use mozaic::modules::{Aggregator, Steplock, game};
|
use mozaic::modules::{Aggregator, Steplock, game};
|
||||||
|
|
||||||
|
|
||||||
|
mod planetwars;
|
||||||
|
|
||||||
// Load the config and start the game.
|
// Load the config and start the game.
|
||||||
fn main() {
|
fn main() {
|
||||||
run(env::args().collect());
|
run(env::args().collect());
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::str;
|
|
||||||
struct Server;
|
|
||||||
impl game::GameController for Server {
|
|
||||||
fn step<'a>(&mut self, turns: Vec<game::PlayerTurn<'a>>) -> Vec<game::Update> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
|
|
||||||
for (id, turn) in turns.iter() {
|
|
||||||
let postfix = match turn {
|
|
||||||
game::Turn::Action(bytes) => str::from_utf8(bytes).unwrap(),
|
|
||||||
game::Turn::Timeout => "Timed out",
|
|
||||||
};
|
|
||||||
|
|
||||||
let msg = format!("{}: {}", **id, postfix);
|
|
||||||
|
|
||||||
out.push(game::Update::Global(msg.as_bytes().to_vec()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use mozaic::server::runtime::{Broker};
|
use mozaic::server::runtime::{Broker};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use errors::Consumable;
|
use errors::Consumable;
|
||||||
|
@ -55,14 +41,21 @@ pub fn run(args : Vec<String>) {
|
||||||
|
|
||||||
let number_of_clients = args.get(1).map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
|
let number_of_clients = args.get(1).map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
|
||||||
|
|
||||||
let ids: HashMap<_, util::PlayerId> = (0..number_of_clients).map(|x| (x.into(), (10 - x).into())).collect();
|
let ids: HashMap<util::Identifier, util::PlayerId> = (0..number_of_clients).map(|x| (rand::thread_rng().gen::<u64>().into(), x.into())).collect();
|
||||||
|
|
||||||
println!("Ids: {:?}", ids);
|
let config = planetwars::Config { map_file: String::from("hex.json"), max_turns: 500 };
|
||||||
|
let game = planetwars::PlanetWarsGame::new(config.create_game(number_of_clients as usize));
|
||||||
|
|
||||||
|
println!("Tokens:");
|
||||||
|
let keys: Vec<u64> = ids.keys().map(|&x| x.into()).collect();
|
||||||
|
for key in keys {
|
||||||
|
println!("key {}", key);
|
||||||
|
}
|
||||||
|
|
||||||
tokio::run(futures::lazy(move || {
|
tokio::run(futures::lazy(move || {
|
||||||
let mut broker = Broker::new().unwrap();
|
let mut broker = Broker::new().unwrap();
|
||||||
|
|
||||||
broker.spawn(welcomer_id.clone(), game::GameReactor::params(steplock_id.clone(), Box::new(Server)), "Main").display();
|
broker.spawn(welcomer_id.clone(), game::GameReactor::params(steplock_id.clone(), Box::new(game)), "Main").display();
|
||||||
broker.spawn(steplock_id.clone(), Steplock::new(broker.clone(), ids.values().cloned().collect(), welcomer_id.clone(), aggregator_id.clone()).with_timeout(5000).params(), "Steplock").display();
|
broker.spawn(steplock_id.clone(), Steplock::new(broker.clone(), ids.values().cloned().collect(), welcomer_id.clone(), aggregator_id.clone()).with_timeout(5000).params(), "Steplock").display();
|
||||||
broker.spawn(aggregator_id.clone(), Aggregator::params(manager_id.clone(), steplock_id.clone()), "Aggregator").display();
|
broker.spawn(aggregator_id.clone(), Aggregator::params(manager_id.clone(), steplock_id.clone()), "Aggregator").display();
|
||||||
broker.spawn(
|
broker.spawn(
|
||||||
|
|
145
backend/src/planetwars/mod.rs
Normal file
145
backend/src/planetwars/mod.rs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
|
||||||
|
use mozaic::modules::game;
|
||||||
|
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
mod pw_config;
|
||||||
|
mod pw_serializer;
|
||||||
|
mod pw_rules;
|
||||||
|
mod pw_protocol;
|
||||||
|
use pw_protocol::{ self as proto, CommandError };
|
||||||
|
use pw_rules::Dispatch;
|
||||||
|
pub use pw_config::Config;
|
||||||
|
|
||||||
|
pub struct PlanetWarsGame {
|
||||||
|
state: pw_rules::PlanetWars,
|
||||||
|
planet_map: HashMap<String, usize>,
|
||||||
|
log_file: File
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlanetWarsGame {
|
||||||
|
|
||||||
|
pub fn new(state: pw_rules::PlanetWars) -> Self {
|
||||||
|
let planet_map = state.planets.iter().map(|p| (p.name.clone(), p.id)).collect();
|
||||||
|
let file = File::create("game.json").unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
state, planet_map,
|
||||||
|
log_file: file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_state(&mut self, were_alive: Vec<usize>, updates: &mut Vec<game::Update>, ) {
|
||||||
|
let state = pw_serializer::serialize(&self.state);
|
||||||
|
write!(self.log_file, "{}\n", serde_json::to_string(&state).unwrap()).unwrap();
|
||||||
|
|
||||||
|
// println!("{}", serde_json::to_string(&state).unwrap());
|
||||||
|
|
||||||
|
for player in self.state.players.iter().filter(|p| were_alive.contains(&p.id)) {
|
||||||
|
let state = pw_serializer::serialize_rotated(&self.state, player.id);
|
||||||
|
let state = if player.alive && !self.state.is_finished() {
|
||||||
|
proto::ServerMessage::GameState(state)
|
||||||
|
} else {
|
||||||
|
proto::ServerMessage::FinalState(state)
|
||||||
|
};
|
||||||
|
|
||||||
|
updates.push(
|
||||||
|
game::Update::Player((player.id as u64).into(), serde_json::to_vec(&state).unwrap())
|
||||||
|
);
|
||||||
|
|
||||||
|
if !player.alive || self.state.is_finished() {
|
||||||
|
updates.push(game::Update::Kick((player.id as u64).into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_commands<'a>(&mut self, turns: Vec<game::PlayerTurn<'a>>, updates: &mut Vec<game::Update>) {
|
||||||
|
for (player_id, command) in turns.into_iter() {
|
||||||
|
let player_num: usize = (*player_id).try_into().unwrap();
|
||||||
|
let action = proto::ServerMessage::PlayerAction(self.execute_action(player_num, command));
|
||||||
|
let serialized_action = serde_json::to_vec(&action).unwrap();
|
||||||
|
updates.push(game::Update::Player(player_id, serialized_action));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_action<'a>(&mut self, player_num: usize, turn: game::Turn<'a>) -> proto::PlayerAction {
|
||||||
|
let turn = match turn {
|
||||||
|
game::Turn::Timeout => return proto::PlayerAction::Timeout,
|
||||||
|
game::Turn::Action(bytes) => bytes,
|
||||||
|
};
|
||||||
|
|
||||||
|
let action: proto::Action = match serde_json::from_slice(&turn) {
|
||||||
|
Err(err) => return proto::PlayerAction::ParseError(err.to_string()),
|
||||||
|
Ok(action) => action,
|
||||||
|
};
|
||||||
|
|
||||||
|
let commands = action.commands.into_iter().map(|command| {
|
||||||
|
match self.check_valid_command(player_num, &command) {
|
||||||
|
Ok(dispatch) => {
|
||||||
|
self.state.dispatch(&dispatch);
|
||||||
|
proto::PlayerCommand {
|
||||||
|
command,
|
||||||
|
error: None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(error) => {
|
||||||
|
proto::PlayerCommand {
|
||||||
|
command,
|
||||||
|
error: Some(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
return proto::PlayerAction::Commands(commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_valid_command(&self, player_num: usize, mv: &proto::Command) -> Result<Dispatch, CommandError> {
|
||||||
|
let origin_id = *self.planet_map
|
||||||
|
.get(&mv.origin)
|
||||||
|
.ok_or(CommandError::OriginDoesNotExist)?;
|
||||||
|
|
||||||
|
let target_id = *self.planet_map
|
||||||
|
.get(&mv.destination)
|
||||||
|
.ok_or(CommandError::DestinationDoesNotExist)?;
|
||||||
|
|
||||||
|
if self.state.planets[origin_id].owner() != Some(player_num) {
|
||||||
|
return Err(CommandError::OriginNotOwned);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.state.planets[origin_id].ship_count() < mv.ship_count {
|
||||||
|
return Err(CommandError::NotEnoughShips);
|
||||||
|
}
|
||||||
|
|
||||||
|
if mv.ship_count == 0 {
|
||||||
|
return Err(CommandError::ZeroShipMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Dispatch {
|
||||||
|
origin: origin_id,
|
||||||
|
target: target_id,
|
||||||
|
ship_count: mv.ship_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl game::GameController for PlanetWarsGame {
|
||||||
|
fn step<'a>(&mut self, turns: Vec<game::PlayerTurn<'a>>) -> Vec<game::Update> {
|
||||||
|
let mut updates = Vec::new();
|
||||||
|
|
||||||
|
let alive = self.state.living_players();
|
||||||
|
|
||||||
|
self.state.repopulate();
|
||||||
|
self.execute_commands(turns, &mut updates);
|
||||||
|
self.state.step();
|
||||||
|
|
||||||
|
self.dispatch_state(alive, &mut updates);
|
||||||
|
|
||||||
|
updates
|
||||||
|
}
|
||||||
|
}
|
80
backend/src/planetwars/pw_config.rs
Normal file
80
backend/src/planetwars/pw_config.rs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
use super::pw_protocol as proto;
|
||||||
|
use super::pw_rules::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub map_file: String,
|
||||||
|
pub max_turns: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn create_game(&self, clients: usize) -> PlanetWars {
|
||||||
|
let planets = self.load_map(clients);
|
||||||
|
let players = (0..clients)
|
||||||
|
.map(|client_id| Player { id: client_id, alive: true })
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
PlanetWars {
|
||||||
|
players: players,
|
||||||
|
planets: planets,
|
||||||
|
expeditions: Vec::new(),
|
||||||
|
expedition_num: 0,
|
||||||
|
turn_num: 0,
|
||||||
|
max_turns: self.max_turns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_map(&self, num_players: usize) -> Vec<Planet> {
|
||||||
|
let map = self.read_map().expect("[PLANET_WARS] reading map failed");
|
||||||
|
|
||||||
|
return map.planets
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(num, planet)| {
|
||||||
|
let mut fleets = Vec::new();
|
||||||
|
let owner = planet.owner.and_then(|owner_num| {
|
||||||
|
// in the current map format, player numbers start at 1.
|
||||||
|
// TODO: we might want to change this.
|
||||||
|
let player_num = owner_num - 1;
|
||||||
|
// ignore players that are not in the game
|
||||||
|
if player_num < num_players {
|
||||||
|
Some(player_num)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if planet.ship_count > 0 {
|
||||||
|
fleets.push(Fleet {
|
||||||
|
owner: owner,
|
||||||
|
ship_count: planet.ship_count,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Planet {
|
||||||
|
id: num,
|
||||||
|
name: planet.name,
|
||||||
|
x: planet.x,
|
||||||
|
y: planet.y,
|
||||||
|
fleets: fleets,
|
||||||
|
};
|
||||||
|
}).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_map(&self) -> io::Result<Map> {
|
||||||
|
let mut file = File::open(&self.map_file)?;
|
||||||
|
let mut buf = String::new();
|
||||||
|
file.read_to_string(&mut buf)?;
|
||||||
|
let map = serde_json::from_str(&buf)?;
|
||||||
|
return Ok(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Map {
|
||||||
|
pub planets: Vec<proto::Planet>,
|
||||||
|
}
|
79
backend/src/planetwars/pw_protocol.rs
Normal file
79
backend/src/planetwars/pw_protocol.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Expedition {
|
||||||
|
pub id: u64,
|
||||||
|
pub ship_count: u64,
|
||||||
|
pub origin: String,
|
||||||
|
pub destination: String,
|
||||||
|
pub owner: usize,
|
||||||
|
pub turns_remaining: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Planet {
|
||||||
|
pub ship_count: u64,
|
||||||
|
pub x: f64,
|
||||||
|
pub y: f64,
|
||||||
|
pub owner: Option<usize>,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Action {
|
||||||
|
#[serde(rename = "moves")]
|
||||||
|
pub commands: Vec<Command>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Command {
|
||||||
|
pub origin: String,
|
||||||
|
pub destination: String,
|
||||||
|
pub ship_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct State {
|
||||||
|
pub planets: Vec<Planet>,
|
||||||
|
pub expeditions: Vec<Expedition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct GameInfo {
|
||||||
|
pub players: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum CommandError {
|
||||||
|
NotEnoughShips,
|
||||||
|
OriginNotOwned,
|
||||||
|
ZeroShipMove,
|
||||||
|
OriginDoesNotExist,
|
||||||
|
DestinationDoesNotExist,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PlayerCommand {
|
||||||
|
pub command: Command,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub error: Option<CommandError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(tag = "type", content = "value")]
|
||||||
|
pub enum PlayerAction {
|
||||||
|
Timeout,
|
||||||
|
ParseError(String),
|
||||||
|
Commands(Vec<PlayerCommand>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(tag = "type", content = "content")]
|
||||||
|
pub enum ServerMessage {
|
||||||
|
/// Game state in current turn
|
||||||
|
GameState(State),
|
||||||
|
/// The action that was performed
|
||||||
|
PlayerAction(PlayerAction),
|
||||||
|
/// The game is over, and this is the concluding state.
|
||||||
|
FinalState(State),
|
||||||
|
}
|
199
backend/src/planetwars/pw_rules.rs
Normal file
199
backend/src/planetwars/pw_rules.rs
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
|
||||||
|
/// The planet wars game rules.
|
||||||
|
pub struct PlanetWars {
|
||||||
|
pub players: Vec<Player>,
|
||||||
|
pub planets: Vec<Planet>,
|
||||||
|
pub expeditions: Vec<Expedition>,
|
||||||
|
// How many expeditions were already dispatched.
|
||||||
|
// This is needed for assigning expedition identifiers.
|
||||||
|
pub expedition_num: u64,
|
||||||
|
pub turn_num: u64,
|
||||||
|
pub max_turns: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Player {
|
||||||
|
pub id: usize,
|
||||||
|
pub alive: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Fleet {
|
||||||
|
pub owner: Option<usize>,
|
||||||
|
pub ship_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Planet {
|
||||||
|
pub id: usize,
|
||||||
|
pub name: String,
|
||||||
|
pub fleets: Vec<Fleet>,
|
||||||
|
pub x: f64,
|
||||||
|
pub y: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Expedition {
|
||||||
|
pub id: u64,
|
||||||
|
pub origin: usize,
|
||||||
|
pub target: usize,
|
||||||
|
pub fleet: Fleet,
|
||||||
|
pub turns_remaining: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Dispatch {
|
||||||
|
pub origin: usize,
|
||||||
|
pub target: usize,
|
||||||
|
pub ship_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlanetWars {
|
||||||
|
|
||||||
|
pub fn dispatch(&mut self, dispatch: &Dispatch) {
|
||||||
|
let distance = self.planets[dispatch.origin].distance(
|
||||||
|
&self.planets[dispatch.target]
|
||||||
|
);
|
||||||
|
|
||||||
|
let origin = &mut self.planets[dispatch.origin];
|
||||||
|
origin.fleets[0].ship_count -= dispatch.ship_count;
|
||||||
|
|
||||||
|
|
||||||
|
let expedition = Expedition {
|
||||||
|
id: self.expedition_num,
|
||||||
|
origin: dispatch.origin,
|
||||||
|
target: dispatch.target,
|
||||||
|
turns_remaining: distance,
|
||||||
|
fleet: Fleet {
|
||||||
|
owner: origin.owner(),
|
||||||
|
ship_count: dispatch.ship_count,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// increment counter
|
||||||
|
self.expedition_num += 1;
|
||||||
|
self.expeditions.push(expedition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play one step of the game
|
||||||
|
pub fn step(&mut self) {
|
||||||
|
self.turn_num += 1;
|
||||||
|
|
||||||
|
// Initially mark all players dead, re-marking them as alive once we
|
||||||
|
// encounter a sign of life.
|
||||||
|
for player in self.players.iter_mut() {
|
||||||
|
player.alive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.step_expeditions();
|
||||||
|
self.resolve_combat();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn repopulate(&mut self) {
|
||||||
|
for planet in self.planets.iter_mut() {
|
||||||
|
if planet.owner().is_some() {
|
||||||
|
planet.fleets[0].ship_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn step_expeditions(&mut self) {
|
||||||
|
let mut i = 0;
|
||||||
|
let exps = &mut self.expeditions;
|
||||||
|
while i < exps.len() {
|
||||||
|
// compare with 1 to avoid issues with planet distance 0
|
||||||
|
if exps[i].turns_remaining <= 1 {
|
||||||
|
// remove expedition from expeditions, and add to fleet
|
||||||
|
let exp = exps.swap_remove(i);
|
||||||
|
let planet = &mut self.planets[exp.target];
|
||||||
|
planet.orbit(exp.fleet);
|
||||||
|
} else {
|
||||||
|
exps[i].turns_remaining -= 1;
|
||||||
|
if let Some(owner_num) = exps[i].fleet.owner {
|
||||||
|
// owner has an expedition in progress; this is a sign of life.
|
||||||
|
self.players[owner_num].alive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// proceed to next expedition
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_combat(&mut self) {
|
||||||
|
for planet in self.planets.iter_mut() {
|
||||||
|
planet.resolve_combat();
|
||||||
|
if let Some(owner_num) = planet.owner() {
|
||||||
|
// owner owns a planet; this is a sign of life.
|
||||||
|
self.players[owner_num].alive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_finished(&self) -> bool {
|
||||||
|
let remaining = self.players.iter().filter(|p| p.alive).count();
|
||||||
|
return remaining < 2 || self.turn_num >= self.max_turns;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn living_players(&self) -> Vec<usize> {
|
||||||
|
self.players.iter().filter_map(|p| {
|
||||||
|
if p.alive {
|
||||||
|
Some(p.id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Planet {
|
||||||
|
pub fn owner(&self) -> Option<usize> {
|
||||||
|
self.fleets.first().and_then(|f| f.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ship_count(&self) -> u64 {
|
||||||
|
self.fleets.first().map_or(0, |f| f.ship_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make a fleet orbit this planet.
|
||||||
|
fn orbit(&mut self, fleet: Fleet) {
|
||||||
|
// If owner already has a fleet present, merge
|
||||||
|
for other in self.fleets.iter_mut() {
|
||||||
|
if other.owner == fleet.owner {
|
||||||
|
other.ship_count += fleet.ship_count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else, add fleet to fleets list
|
||||||
|
self.fleets.push(fleet);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_combat(&mut self) {
|
||||||
|
// The player owning the largest fleet present will win the combat.
|
||||||
|
// Here, we resolve how many ships he will have left.
|
||||||
|
// note: in the current implementation, we could resolve by doing
|
||||||
|
// winner.ship_count -= second_largest.ship_count, but this does not
|
||||||
|
// allow for simple customizations (such as changing combat balance).
|
||||||
|
|
||||||
|
self.fleets.sort_by(|a, b| a.ship_count.cmp(&b.ship_count).reverse());
|
||||||
|
while self.fleets.len() > 1 {
|
||||||
|
let fleet = self.fleets.pop().unwrap();
|
||||||
|
// destroy some ships
|
||||||
|
for other in self.fleets.iter_mut() {
|
||||||
|
other.ship_count -= fleet.ship_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove dead fleets
|
||||||
|
while self.fleets.last().map(|f| f.ship_count) == Some(0) {
|
||||||
|
self.fleets.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distance(&self, other: &Planet) -> u64 {
|
||||||
|
let dx = self.x - other.x;
|
||||||
|
let dy = self.y - other.y;
|
||||||
|
return (dx.powi(2) + dy.powi(2)).sqrt().ceil() as u64;
|
||||||
|
}
|
||||||
|
}
|
74
backend/src/planetwars/pw_serializer.rs
Normal file
74
backend/src/planetwars/pw_serializer.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
use super::pw_rules::{PlanetWars, Planet, Expedition};
|
||||||
|
use super::pw_protocol as proto;
|
||||||
|
|
||||||
|
/// Serialize given gamestate
|
||||||
|
pub fn serialize(state: &PlanetWars) -> proto::State {
|
||||||
|
serialize_rotated(state, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialize given gamestate with player numbers rotated by given offset.
|
||||||
|
pub fn serialize_rotated(state: &PlanetWars, offset: usize) -> proto::State {
|
||||||
|
let serializer = Serializer::new(state, offset);
|
||||||
|
serializer.serialize_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Serializer<'a> {
|
||||||
|
state: &'a PlanetWars,
|
||||||
|
player_num_offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Serializer<'a> {
|
||||||
|
fn new(state: &'a PlanetWars, offset: usize) -> Self {
|
||||||
|
Serializer {
|
||||||
|
state: state,
|
||||||
|
player_num_offset: offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_state(&self) -> proto::State {
|
||||||
|
proto::State {
|
||||||
|
planets: self.state
|
||||||
|
.planets
|
||||||
|
.iter()
|
||||||
|
.map(|planet| self.serialize_planet(planet))
|
||||||
|
.collect(),
|
||||||
|
expeditions: self.state
|
||||||
|
.expeditions
|
||||||
|
.iter()
|
||||||
|
.map(|exp| self.serialize_expedition(exp))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the player number for given player id.
|
||||||
|
/// Player numbers are 1-based (as opposed to player ids), They will also be
|
||||||
|
/// rotated based on the number offset for this serializer.
|
||||||
|
fn player_num(&self, player_id: usize) -> usize {
|
||||||
|
let num_players = self.state.players.len();
|
||||||
|
let rotated_id = (player_id + self.player_num_offset) % num_players;
|
||||||
|
// protocol player ids start at 1
|
||||||
|
return rotated_id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_planet(&self, planet: &Planet) -> proto::Planet {
|
||||||
|
proto::Planet {
|
||||||
|
name: planet.name.clone(),
|
||||||
|
x: planet.x,
|
||||||
|
y: planet.y,
|
||||||
|
owner: planet.owner().map(|id| self.player_num(id)),
|
||||||
|
ship_count: planet.ship_count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_expedition(&self, exp: &Expedition) -> proto::Expedition {
|
||||||
|
proto::Expedition {
|
||||||
|
id: exp.id,
|
||||||
|
owner: self.player_num(exp.fleet.owner.unwrap()),
|
||||||
|
ship_count: exp.fleet.ship_count,
|
||||||
|
origin: self.state.planets[exp.origin as usize].name.clone(),
|
||||||
|
destination: self.state.planets[exp.target as usize].name.clone(),
|
||||||
|
turns_remaining: exp.turns_remaining,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
backend/standard_game.json
Normal file
82
backend/standard_game.json
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
{"players":["bot_auto_player_full_rand","adversary_auto_player_orfirst_rand"]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":0,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":1,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":0,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":1,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":0,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":1,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":2,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":3,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":0,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":1,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":2,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":3,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":4,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":5,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":0,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":1,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":2,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":3,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":4,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":5,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":6,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":7,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":6,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":2,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":3,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":4,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":5,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":7,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":6,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":2,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":3,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":4,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":5,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":8,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":0,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":7,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":6,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":10,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":10},{"id":4,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":5,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":8,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":7,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":6,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":10,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":9},{"id":12,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":11,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":8,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":7,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":14,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":10,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":8},{"id":12,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":11,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":8,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":13,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":16,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":14,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":10,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":7},{"id":12,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":11,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":13,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":16,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":14,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":10,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":6},{"id":12,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":11,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":18,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":13,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":17,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":16,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":14,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":20,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":5},{"id":12,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":11,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":18,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":13,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":15,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":17,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":19,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":16,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":14,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":20,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":4},{"id":22,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":18,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":13,"ship_count":3,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":15,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":17,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":19,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":16,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":24,"ship_count":3,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":20,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":3},{"id":22,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":18,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":23,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":15,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":17,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":19,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":7,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":26,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":24,"ship_count":3,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":20,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":2},{"id":22,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":21,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":18,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":23,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":10},{"id":17,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":19,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":26,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":24,"ship_count":3,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":20,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":9,"ship_count":4,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":1},{"id":22,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":21,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":28,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":23,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":9},{"id":27,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":19,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":26,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":24,"ship_count":3,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":30,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":29,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":22,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":28,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":23,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":8},{"id":27,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":26,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":24,"ship_count":3,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":30,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":29,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":32,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":31,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":28,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":23,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":7},{"id":27,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":26,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":34,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":30,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":29,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":32,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":31,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":28,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":33,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":6},{"id":27,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":36,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":34,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":30,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":29,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":32,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":31,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":28,"ship_count":3,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":33,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":5},{"id":27,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":35,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":36,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":34,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":30,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":29,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":32,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":31,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":38,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":33,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":4},{"id":37,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":35,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":36,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":34,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":40,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":39,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":32,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":31,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":38,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":33,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":3},{"id":37,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":35,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":36,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":34,"ship_count":4,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":40,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":39,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":42,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":41,"ship_count":5,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":38,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":33,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":2},{"id":37,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":35,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":36,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":44,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":40,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":39,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":42,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":41,"ship_count":5,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":38,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":43,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":25,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":2,"turns_remaining":1},{"id":37,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":35,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":0,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":46,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":44,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":40,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":39,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":42,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":41,"ship_count":5,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":38,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":43,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":45,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":37,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":46,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":44,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":40,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":39,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":42,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":41,"ship_count":5,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":48,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":43,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":45,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":47,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":46,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":44,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":49,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":47,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":42,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":41,"ship_count":5,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":48,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":43,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":45,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":0,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":46,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":44,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":49,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":47,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":51,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":50,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":48,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":43,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":45,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":46,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":53,"ship_count":4,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":49,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":47,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":51,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":50,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":48,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":52,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":45,"ship_count":3,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":0,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":54,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":53,"ship_count":4,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":49,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":47,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":51,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":50,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":48,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":52,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":5,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":54,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":53,"ship_count":4,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":49,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":56,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":51,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":50,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":55,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":52,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":54,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":53,"ship_count":4,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":58,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":56,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":51,"ship_count":2,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":50,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":55,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":52,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":57,"ship_count":1,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":54,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":53,"ship_count":4,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":58,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":56,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":59,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":57,"ship_count":1,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":55,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":52,"ship_count":3,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":54,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":10},{"id":58,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":56,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":59,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":57,"ship_count":1,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":55,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":60,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":0,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":63,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":9},{"id":58,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":56,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":59,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":57,"ship_count":1,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":55,"ship_count":2,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":60,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":62,"ship_count":6,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":63,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":8},{"id":58,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":65,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":59,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":57,"ship_count":1,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":64,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":60,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":62,"ship_count":6,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":63,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":7},{"id":67,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":65,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":59,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":66,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":64,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":60,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":62,"ship_count":6,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":63,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":6},{"id":67,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":65,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":69,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":66,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":64,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":60,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":62,"ship_count":6,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":68,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":7,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":63,"ship_count":5,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":67,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":65,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":69,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":66,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":64,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":71,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":62,"ship_count":6,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":68,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":70,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":73,"ship_count":6,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":67,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":65,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":69,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":66,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":64,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":71,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":72,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":68,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":70,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":73,"ship_count":6,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":67,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":75,"ship_count":4,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":69,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":66,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":74,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":71,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":72,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":68,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":70,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":73,"ship_count":6,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":76,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":75,"ship_count":4,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":69,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":70,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":74,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":71,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":72,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":68,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":73,"ship_count":6,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":61,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":76,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":75,"ship_count":4,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":78,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":70,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":74,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":71,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":72,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":77,"ship_count":5,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":5,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":73,"ship_count":6,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":80,"ship_count":5,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":76,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":75,"ship_count":4,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":78,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":79,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":5},{"id":74,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":77,"ship_count":5,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":72,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":0,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":81,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":80,"ship_count":5,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":76,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":75,"ship_count":4,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":78,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":79,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":4},{"id":74,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":77,"ship_count":5,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":81,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":80,"ship_count":5,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":76,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":82,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":78,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":79,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":3},{"id":77,"ship_count":5,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":81,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":80,"ship_count":5,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":84,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":82,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":78,"ship_count":2,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":79,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":2},{"id":77,"ship_count":5,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":83,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":81,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":80,"ship_count":5,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":84,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":82,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":10},{"id":79,"ship_count":1,"origin":"protos","destination":"duteros","owner":1,"turns_remaining":1},{"id":85,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":83,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":8,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":81,"ship_count":1,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":87,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":84,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":82,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":9},{"id":83,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":85,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":89,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":87,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":84,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":82,"ship_count":1,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":8},{"id":83,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":85,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":88,"ship_count":8,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":89,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":87,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":84,"ship_count":4,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":91,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":7},{"id":83,"ship_count":2,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":85,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":88,"ship_count":8,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":90,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":89,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":87,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":93,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":5},{"id":91,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":6},{"id":92,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":85,"ship_count":2,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":88,"ship_count":8,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":90,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":89,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":87,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":93,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":4},{"id":91,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":92,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":95,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":5},{"id":88,"ship_count":8,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":90,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":94,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":89,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":96,"ship_count":5,"origin":"protos","destination":"helios","owner":1,"turns_remaining":5},{"id":93,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":3},{"id":91,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":92,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":95,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":4},{"id":88,"ship_count":8,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":90,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":94,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":98,"ship_count":3,"origin":"extos","destination":"helios","owner":1,"turns_remaining":5},{"id":96,"ship_count":5,"origin":"protos","destination":"helios","owner":1,"turns_remaining":4},{"id":93,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":2},{"id":91,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":92,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":95,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":3},{"id":97,"ship_count":5,"origin":"pemptos","destination":"helios","owner":2,"turns_remaining":5},{"id":90,"ship_count":3,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":94,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":98,"ship_count":3,"origin":"extos","destination":"helios","owner":1,"turns_remaining":4},{"id":96,"ship_count":5,"origin":"protos","destination":"helios","owner":1,"turns_remaining":3},{"id":93,"ship_count":3,"origin":"tritos","destination":"duteros","owner":2,"turns_remaining":1},{"id":100,"ship_count":2,"origin":"extos","destination":"helios","owner":1,"turns_remaining":5},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":92,"ship_count":6,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1},{"id":95,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":2},{"id":97,"ship_count":5,"origin":"pemptos","destination":"helios","owner":2,"turns_remaining":4},{"id":99,"ship_count":3,"origin":"duteros","destination":"helios","owner":2,"turns_remaining":5},{"id":94,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":7,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":0,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":98,"ship_count":3,"origin":"extos","destination":"helios","owner":1,"turns_remaining":3},{"id":96,"ship_count":5,"origin":"protos","destination":"helios","owner":1,"turns_remaining":2},{"id":102,"ship_count":3,"origin":"tetartos","destination":"helios","owner":2,"turns_remaining":5},{"id":100,"ship_count":2,"origin":"extos","destination":"helios","owner":1,"turns_remaining":4},{"id":86,"ship_count":4,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":101,"ship_count":3,"origin":"protos","destination":"helios","owner":1,"turns_remaining":5},{"id":95,"ship_count":2,"origin":"tetartos","destination":"tritos","owner":2,"turns_remaining":1},{"id":97,"ship_count":5,"origin":"pemptos","destination":"helios","owner":2,"turns_remaining":3},{"id":99,"ship_count":3,"origin":"duteros","destination":"helios","owner":2,"turns_remaining":4},{"id":94,"ship_count":1,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":null,"name":"helios"}],"expeditions":[{"id":98,"ship_count":3,"origin":"extos","destination":"helios","owner":1,"turns_remaining":2},{"id":96,"ship_count":5,"origin":"protos","destination":"helios","owner":1,"turns_remaining":1},{"id":102,"ship_count":3,"origin":"tetartos","destination":"helios","owner":2,"turns_remaining":4},{"id":100,"ship_count":2,"origin":"extos","destination":"helios","owner":1,"turns_remaining":3},{"id":104,"ship_count":7,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":5},{"id":101,"ship_count":3,"origin":"protos","destination":"helios","owner":1,"turns_remaining":4},{"id":103,"ship_count":2,"origin":"extos","destination":"protos","owner":1,"turns_remaining":5},{"id":97,"ship_count":5,"origin":"pemptos","destination":"helios","owner":2,"turns_remaining":2},{"id":99,"ship_count":3,"origin":"duteros","destination":"helios","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":1,"x":0.0,"y":0.0,"owner":1,"name":"helios"}],"expeditions":[{"id":98,"ship_count":3,"origin":"extos","destination":"helios","owner":1,"turns_remaining":1},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":10},{"id":102,"ship_count":3,"origin":"tetartos","destination":"helios","owner":2,"turns_remaining":3},{"id":100,"ship_count":2,"origin":"extos","destination":"helios","owner":1,"turns_remaining":2},{"id":104,"ship_count":7,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":4},{"id":101,"ship_count":3,"origin":"protos","destination":"helios","owner":1,"turns_remaining":3},{"id":103,"ship_count":2,"origin":"extos","destination":"protos","owner":1,"turns_remaining":4},{"id":97,"ship_count":5,"origin":"pemptos","destination":"helios","owner":2,"turns_remaining":1},{"id":99,"ship_count":3,"origin":"duteros","destination":"helios","owner":2,"turns_remaining":2},{"id":105,"ship_count":1,"origin":"extos","destination":"protos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":1,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":108,"ship_count":1,"origin":"helios","destination":"extos","owner":1,"turns_remaining":5},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":9},{"id":102,"ship_count":3,"origin":"tetartos","destination":"helios","owner":2,"turns_remaining":2},{"id":100,"ship_count":2,"origin":"extos","destination":"helios","owner":1,"turns_remaining":1},{"id":104,"ship_count":7,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":3},{"id":101,"ship_count":3,"origin":"protos","destination":"helios","owner":1,"turns_remaining":2},{"id":103,"ship_count":2,"origin":"extos","destination":"protos","owner":1,"turns_remaining":3},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":9},{"id":99,"ship_count":3,"origin":"duteros","destination":"helios","owner":2,"turns_remaining":1},{"id":105,"ship_count":1,"origin":"extos","destination":"protos","owner":1,"turns_remaining":4}]}
|
||||||
|
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":1,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":3,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":108,"ship_count":1,"origin":"helios","destination":"extos","owner":1,"turns_remaining":4},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":8},{"id":102,"ship_count":3,"origin":"tetartos","destination":"helios","owner":2,"turns_remaining":1},{"id":109,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":5},{"id":104,"ship_count":7,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":2},{"id":101,"ship_count":3,"origin":"protos","destination":"helios","owner":1,"turns_remaining":1},{"id":103,"ship_count":2,"origin":"extos","destination":"protos","owner":1,"turns_remaining":2},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":8},{"id":105,"ship_count":1,"origin":"extos","destination":"protos","owner":1,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":5,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":2,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":4,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":108,"ship_count":1,"origin":"helios","destination":"extos","owner":1,"turns_remaining":3},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":7},{"id":111,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":109,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":4},{"id":104,"ship_count":7,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":1},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":10},{"id":103,"ship_count":2,"origin":"extos","destination":"protos","owner":1,"turns_remaining":1},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":7},{"id":105,"ship_count":1,"origin":"extos","destination":"protos","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":0,"x":-6.0,"y":0.0,"owner":null,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":3,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":5,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":1,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":108,"ship_count":1,"origin":"helios","destination":"extos","owner":1,"turns_remaining":2},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":6},{"id":111,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":109,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":3},{"id":113,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":5},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":9},{"id":112,"ship_count":4,"origin":"helios","destination":"extos","owner":2,"turns_remaining":5},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":6},{"id":105,"ship_count":1,"origin":"extos","destination":"protos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":6,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":1,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":2,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":108,"ship_count":1,"origin":"helios","destination":"extos","owner":1,"turns_remaining":1},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":5},{"id":111,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":109,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":2},{"id":113,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":4},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":8},{"id":112,"ship_count":4,"origin":"helios","destination":"extos","owner":2,"turns_remaining":4},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":5},{"id":115,"ship_count":4,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":5},{"id":114,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":5,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":2,"x":-3.0,"y":-5.0,"owner":1,"name":"extos"},{"ship_count":3,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":117,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":4},{"id":111,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":109,"ship_count":4,"origin":"pemptos","destination":"extos","owner":2,"turns_remaining":1},{"id":113,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":3},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":7},{"id":112,"ship_count":4,"origin":"helios","destination":"extos","owner":2,"turns_remaining":3},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":4},{"id":115,"ship_count":4,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":4},{"id":114,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":116,"ship_count":5,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":2,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":117,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":3},{"id":111,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":119,"ship_count":2,"origin":"helios","destination":"protos","owner":2,"turns_remaining":5},{"id":113,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":2},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":6},{"id":112,"ship_count":4,"origin":"helios","destination":"extos","owner":2,"turns_remaining":2},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":3},{"id":115,"ship_count":4,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":3},{"id":114,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":116,"ship_count":5,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":118,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":7,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":3,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":3,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":117,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":2},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":9},{"id":119,"ship_count":2,"origin":"helios","destination":"protos","owner":2,"turns_remaining":4},{"id":113,"ship_count":1,"origin":"protos","destination":"extos","owner":1,"turns_remaining":1},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":5},{"id":112,"ship_count":4,"origin":"helios","destination":"extos","owner":2,"turns_remaining":1},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":2},{"id":115,"ship_count":4,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":2},{"id":114,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":116,"ship_count":5,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":118,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":1,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":8,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":7,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":4,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":117,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":106,"ship_count":3,"origin":"tetartos","destination":"extos","owner":2,"turns_remaining":1},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":119,"ship_count":2,"origin":"helios","destination":"protos","owner":2,"turns_remaining":3},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":10},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":4},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":9},{"id":107,"ship_count":2,"origin":"duteros","destination":"extos","owner":2,"turns_remaining":1},{"id":115,"ship_count":4,"origin":"duteros","destination":"protos","owner":2,"turns_remaining":1},{"id":114,"ship_count":5,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":116,"ship_count":5,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":118,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":9}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":6,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":4,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":5,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":117,"ship_count":1,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1},{"id":125,"ship_count":7,"origin":"extos","destination":"helios","owner":2,"turns_remaining":5},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":119,"ship_count":2,"origin":"helios","destination":"protos","owner":2,"turns_remaining":2},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":9},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":3},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":124,"ship_count":1,"origin":"protos","destination":"helios","owner":1,"turns_remaining":5},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":8},{"id":118,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":116,"ship_count":5,"origin":"tetartos","destination":"pemptos","owner":2,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":2,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":7,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":9,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":7,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":6,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":11},{"id":125,"ship_count":7,"origin":"extos","destination":"helios","owner":2,"turns_remaining":4},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":119,"ship_count":2,"origin":"helios","destination":"protos","owner":2,"turns_remaining":1},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":8},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":2},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":124,"ship_count":1,"origin":"protos","destination":"helios","owner":1,"turns_remaining":4},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":7},{"id":118,"ship_count":2,"origin":"extos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":7,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":8,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":8,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":8,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":5,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":10},{"id":125,"ship_count":7,"origin":"extos","destination":"helios","owner":2,"turns_remaining":3},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":127,"ship_count":2,"origin":"helios","destination":"duteros","owner":2,"turns_remaining":5},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":7},{"id":110,"ship_count":4,"origin":"tritos","destination":"protos","owner":2,"turns_remaining":1},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":124,"ship_count":1,"origin":"protos","destination":"helios","owner":1,"turns_remaining":3},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":6}]}
|
||||||
|
{"planets":[{"ship_count":12,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":9,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":9,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":9,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":6,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":9},{"id":125,"ship_count":7,"origin":"extos","destination":"helios","owner":2,"turns_remaining":2},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":127,"ship_count":2,"origin":"helios","destination":"duteros","owner":2,"turns_remaining":4},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":6},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":124,"ship_count":1,"origin":"protos","destination":"helios","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":13,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":2,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":10,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":10,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":10,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":7,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":8},{"id":125,"ship_count":7,"origin":"extos","destination":"helios","owner":2,"turns_remaining":1},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":3},{"id":127,"ship_count":2,"origin":"helios","destination":"duteros","owner":2,"turns_remaining":3},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":5},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":124,"ship_count":1,"origin":"protos","destination":"helios","owner":1,"turns_remaining":1},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":9}]}
|
||||||
|
{"planets":[{"ship_count":14,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":3,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":11,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":11,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":11,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":14,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":7},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":8},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":127,"ship_count":2,"origin":"helios","destination":"duteros","owner":2,"turns_remaining":2},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":4},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":15,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":7,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":4,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":12,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":12,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":12,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":9,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":6},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":7},{"id":121,"ship_count":5,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":127,"ship_count":2,"origin":"helios","destination":"duteros","owner":2,"turns_remaining":1},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":3},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":2},{"id":129,"ship_count":6,"origin":"helios","destination":"protos","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":16,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":10,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":5,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":13,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":18,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":13,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":10,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":5},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":6},{"id":129,"ship_count":6,"origin":"helios","destination":"protos","owner":2,"turns_remaining":4},{"id":122,"ship_count":1,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":1},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":2},{"id":120,"ship_count":3,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":17,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":11,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":14,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":17,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":14,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":8,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":4},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":5},{"id":129,"ship_count":6,"origin":"helios","destination":"protos","owner":2,"turns_remaining":3},{"id":130,"ship_count":3,"origin":"helios","destination":"extos","owner":2,"turns_remaining":5},{"id":123,"ship_count":1,"origin":"protos","destination":"pemptos","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":18,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":12,"x":-3.0,"y":5.0,"owner":2,"name":"duteros"},{"ship_count":7,"x":3.0,"y":5.0,"owner":2,"name":"tritos"},{"ship_count":15,"x":6.0,"y":0.0,"owner":2,"name":"tetartos"},{"ship_count":17,"x":3.0,"y":-5.0,"owner":2,"name":"pemptos"},{"ship_count":10,"x":-3.0,"y":-5.0,"owner":2,"name":"extos"},{"ship_count":9,"x":0.0,"y":0.0,"owner":2,"name":"helios"}],"expeditions":[{"id":126,"ship_count":5,"origin":"duteros","destination":"pemptos","owner":2,"turns_remaining":3},{"id":128,"ship_count":4,"origin":"tritos","destination":"pemptos","owner":2,"turns_remaining":4},{"id":129,"ship_count":6,"origin":"helios","destination":"protos","owner":2,"turns_remaining":2},{"id":130,"ship_count":3,"origin":"helios","destination":"extos","owner":2,"turns_remaining":4},{"id":131,"ship_count":5,"origin":"extos","destination":"duteros","owner":2,"turns_remaining":9}]}
|
|
@ -7,3 +7,11 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
mozaic = { git = "https://github.com/ajuvercr/MOZAIC" }
|
||||||
|
tokio = "0.1.22"
|
||||||
|
capnp = "0.10.1"
|
||||||
|
futures = "0.1.28"
|
||||||
|
serde = "1.0.100"
|
||||||
|
serde_derive = "1.0.100"
|
||||||
|
serde_json = "1.0"
|
||||||
|
rand = { version = "0.6.5", default-features = true }
|
||||||
|
|
23
client/bot7.txt
Normal file
23
client/bot7.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
start{"planets":[{"ship_count":7,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":7,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":0,"ship_count":6,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":0,"x":-3.0,"y":5.0,"owner":null,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":1,"ship_count":6,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":6,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":10},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":12,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":9},{"id":2,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1},{"id":3,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":1},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":1,"turns_remaining":5},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5},{"id":14,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":11}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":8},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":11},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":5},{"id":4,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1},{"id":5,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":1},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":1,"turns_remaining":4},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":10},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5},{"id":16,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":7},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":10},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":4},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":6,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1},{"id":7,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":1},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":1,"turns_remaining":3},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":9},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":18,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":6},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":9},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":3},{"id":20,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":8,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1},{"id":9,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":1},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":1,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":8}]}
|
||||||
|
{"planets":[{"ship_count":1,"x":-6.0,"y":0.0,"owner":2,"name":"protos"},{"ship_count":1,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":11,"ship_count":1,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":5},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":8},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":7},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2},{"id":13,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1},{"id":23,"ship_count":5,"origin":"duteros","destination":"protos","owner":1,"turns_remaining":1},{"id":10,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":1,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":15,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":4},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":7},{"id":24,"ship_count":1,"origin":"protos","destination":"duteros","owner":2,"turns_remaining":1},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":6},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":10},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":3},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":6},{"id":17,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":5},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":3,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":9},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":2},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":5},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":4},{"id":19,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1}]}
|
||||||
|
{"planets":[{"ship_count":2,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":5,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":4,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":8},{"id":21,"ship_count":1,"origin":"tetartos","destination":"duteros","owner":1,"turns_remaining":1},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":4},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":3},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":10}]}
|
||||||
|
{"planets":[{"ship_count":3,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":3,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":5,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":7},{"id":29,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":5},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":3},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":3},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":2},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":9}]}
|
||||||
|
{"planets":[{"ship_count":4,"x":-6.0,"y":0.0,"owner":1,"name":"protos"},{"ship_count":4,"x":-3.0,"y":5.0,"owner":1,"name":"duteros"},{"ship_count":6,"x":3.0,"y":5.0,"owner":null,"name":"tritos"},{"ship_count":2,"x":6.0,"y":0.0,"owner":1,"name":"tetartos"},{"ship_count":6,"x":3.0,"y":-5.0,"owner":null,"name":"pemptos"},{"ship_count":6,"x":-3.0,"y":-5.0,"owner":null,"name":"extos"}],"expeditions":[{"id":26,"ship_count":3,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":6},{"id":29,"ship_count":4,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":4},{"id":25,"ship_count":2,"origin":"tetartos","destination":"protos","owner":1,"turns_remaining":2},{"id":27,"ship_count":3,"origin":"duteros","destination":"tritos","owner":1,"turns_remaining":2},{"id":22,"ship_count":1,"origin":"protos","destination":"tetartos","owner":2,"turns_remaining":1},{"id":28,"ship_count":2,"origin":"protos","destination":"tritos","owner":1,"turns_remaining":8},{"id":30,"ship_count":4,"origin":"tetartos","destination":"tritos","owner":1,"turns_remaining":5}]}
|
0
client/log.log
Normal file
0
client/log.log
Normal file
4
client/run.sh
Executable file
4
client/run.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
rm bot*.txt
|
||||||
|
cargo run $1 python simple.py
|
29
client/simple.py
Normal file
29
client/simple.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import sys, json, random
|
||||||
|
|
||||||
|
def move(command):
|
||||||
|
record = { 'moves': [command] }
|
||||||
|
print(json.dumps(record))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
f_name = f"bot{random.randint(0, 10)}.txt"
|
||||||
|
f = open(f_name,"w+")
|
||||||
|
f.write("start")
|
||||||
|
f.flush()
|
||||||
|
for line in sys.stdin:
|
||||||
|
f.write(line)
|
||||||
|
f.flush()
|
||||||
|
state = json.loads(line)
|
||||||
|
# find planet with most ships
|
||||||
|
my_planets = [p for p in state['planets'] if p['owner'] == 1]
|
||||||
|
other_planets = [p for p in state['planets'] if p['owner'] != 1]
|
||||||
|
|
||||||
|
if not my_planets or not other_planets:
|
||||||
|
move(None)
|
||||||
|
else:
|
||||||
|
planet = max(my_planets, key=lambda p: p['ship_count'])
|
||||||
|
dest = min(other_planets, key=lambda p: p['ship_count'])
|
||||||
|
move({
|
||||||
|
'origin': planet['name'],
|
||||||
|
'destination': dest['name'],
|
||||||
|
'ship_count': planet['ship_count'] - 1
|
||||||
|
})
|
|
@ -1,3 +1,290 @@
|
||||||
|
extern crate mozaic;
|
||||||
|
extern crate tokio;
|
||||||
|
extern crate futures;
|
||||||
|
extern crate capnp;
|
||||||
|
extern crate rand;
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use mozaic::core_capnp::{initialize, terminate_stream, identify, actor_joined};
|
||||||
|
use mozaic::messaging::reactor::*;
|
||||||
|
use mozaic::messaging::types::*;
|
||||||
|
use mozaic::errors::*;
|
||||||
|
use mozaic::client_capnp::{client_message, host_message, client_kicked};
|
||||||
|
use mozaic::mozaic_cmd_capnp::{bot_input, bot_return};
|
||||||
|
use mozaic::server::runtime::{Broker, BrokerHandle};
|
||||||
|
use mozaic::server;
|
||||||
|
use mozaic::modules::{BotReactor};
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let id = args.get(1).unwrap().parse().unwrap();
|
||||||
|
let client_args = args.get(2..).expect("How do you expect me to spawn your bot?").to_vec();
|
||||||
|
|
||||||
|
let addr = "127.0.0.1:9142".parse().unwrap();
|
||||||
|
let self_id: ReactorId = rand::thread_rng().gen();
|
||||||
|
|
||||||
|
tokio::run(futures::lazy(move || {
|
||||||
|
let mut broker = Broker::new().unwrap();
|
||||||
|
let reactor = ClientReactor {
|
||||||
|
server: None,
|
||||||
|
id,
|
||||||
|
broker: broker.clone(),
|
||||||
|
args: client_args,
|
||||||
|
};
|
||||||
|
broker.spawn(self_id.clone(), reactor.params(), "main").display();
|
||||||
|
|
||||||
|
tokio::spawn(server::connect_to_server(broker, self_id, &addr));
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main client logic
|
||||||
|
/// ? greeter_id is the server, the tcp stream that you connected to
|
||||||
|
/// ? runtime_id is your own runtime, to handle visualisation etc
|
||||||
|
/// ? user are you ...
|
||||||
|
struct ClientReactor {
|
||||||
|
server: Option<ReactorId>,
|
||||||
|
broker: BrokerHandle,
|
||||||
|
id: u64,
|
||||||
|
args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientReactor {
|
||||||
|
fn params<C: Ctx>(self) -> CoreParams<Self, C> {
|
||||||
|
let mut params = CoreParams::new(self);
|
||||||
|
params.handler(initialize::Owned, CtxHandler::new(Self::initialize));
|
||||||
|
params.handler(actor_joined::Owned, CtxHandler::new(Self::open_host));
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reactor setup
|
||||||
|
fn initialize<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut ReactorHandle<C>,
|
||||||
|
_: initialize::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
// open link with runtime, for communicating with chat GUI
|
||||||
|
let runtime_link = RuntimeLink::params(handle.id().clone());
|
||||||
|
handle.open_link(runtime_link)?;
|
||||||
|
|
||||||
|
let bot = BotReactor::new(self.broker.clone(), handle.id().clone(), self.args.clone());
|
||||||
|
let bot_id = handle.spawn(bot.params(), "Bot Driver")?;
|
||||||
|
|
||||||
|
handle.open_link(BotLink::params(bot_id))?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_host<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut ReactorHandle<C>,
|
||||||
|
r: actor_joined::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
let id = r.get_id()?;
|
||||||
|
|
||||||
|
if let Some(server) = &self.server {
|
||||||
|
handle.open_link(HostLink::params(ReactorId::from(id)))?;
|
||||||
|
self.broker.register_as(id.into(), server.clone());
|
||||||
|
|
||||||
|
// Fake bot msg
|
||||||
|
let mut chat_message = MsgBuffer::<bot_return::Owned>::new();
|
||||||
|
chat_message.build(|b| {
|
||||||
|
b.set_message(b"");
|
||||||
|
});
|
||||||
|
handle.send_internal(chat_message)?;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
handle.open_link(ServerLink::params(id.into()))?;
|
||||||
|
self.server = Some(id.into());
|
||||||
|
|
||||||
|
let mut identify = MsgBuffer::<identify::Owned>::new();
|
||||||
|
identify.build(|b| {
|
||||||
|
b.set_key(self.id);
|
||||||
|
});
|
||||||
|
handle.send_internal(identify).display();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler for the connection with the chat server
|
||||||
|
struct ServerLink;
|
||||||
|
impl ServerLink {
|
||||||
|
fn params<C: Ctx>(foreign_id: ReactorId) -> LinkParams<Self, C> {
|
||||||
|
let mut params = LinkParams::new(foreign_id, Self);
|
||||||
|
|
||||||
|
params.external_handler( terminate_stream::Owned, CtxHandler::new(Self::close_handler) );
|
||||||
|
params.external_handler( actor_joined::Owned, CtxHandler::new(actor_joined::e_to_i) );
|
||||||
|
|
||||||
|
params.internal_handler( identify::Owned, CtxHandler::new(Self::identify) );
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn identify<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut LinkHandle<C>,
|
||||||
|
id: identify::Reader,
|
||||||
|
) -> Result<()> {
|
||||||
|
let id = id.get_key();
|
||||||
|
|
||||||
|
let mut chat_message = MsgBuffer::<identify::Owned>::new();
|
||||||
|
chat_message.build(|b| {
|
||||||
|
b.set_key(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
handle.send_message(chat_message).display();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_handler<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut LinkHandle<C>,
|
||||||
|
_: terminate_stream::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
// also close our end of the stream
|
||||||
|
handle.close_link()?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HostLink;
|
||||||
|
impl HostLink {
|
||||||
|
fn params<C: Ctx>(remote_id: ReactorId) -> LinkParams<Self, C> {
|
||||||
|
let mut params = LinkParams::new(remote_id, HostLink);
|
||||||
|
|
||||||
|
params.external_handler(
|
||||||
|
host_message::Owned,
|
||||||
|
CtxHandler::new(Self::receive_host_message),
|
||||||
|
);
|
||||||
|
|
||||||
|
params.internal_handler(
|
||||||
|
bot_return::Owned,
|
||||||
|
CtxHandler::new(Self::send_chat_message),
|
||||||
|
);
|
||||||
|
|
||||||
|
params.external_handler(
|
||||||
|
client_kicked::Owned,
|
||||||
|
CtxHandler::new(Self::client_kicked),
|
||||||
|
);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick up a 'send_message' event from the reactor, and put it to effect
|
||||||
|
// by constructing the chat message and sending it to the chat server.
|
||||||
|
fn send_chat_message<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut LinkHandle<C>,
|
||||||
|
send_message: bot_return::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
let message = send_message.get_message()?;
|
||||||
|
|
||||||
|
println!("Our bot sent");
|
||||||
|
println!("{}", str::from_utf8(&message).unwrap());
|
||||||
|
|
||||||
|
let mut chat_message = MsgBuffer::<client_message::Owned>::new();
|
||||||
|
chat_message.build(|b| {
|
||||||
|
b.set_data(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
handle.send_message(chat_message)?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick up a 'send_message' event from the reactor, and put it to effect
|
||||||
|
// by constructing the chat message and sending it to the chat server.
|
||||||
|
fn client_kicked<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut LinkHandle<C>,
|
||||||
|
_: client_kicked::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
// Disconnect
|
||||||
|
|
||||||
|
handle.close_link()?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive a chat message from the chat server, and broadcast it on the
|
||||||
|
// reactor.
|
||||||
|
fn receive_host_message<C: Ctx>(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut LinkHandle<C>,
|
||||||
|
host_message: host_message::Reader,
|
||||||
|
) -> Result<()>
|
||||||
|
{
|
||||||
|
let message = host_message.get_data()?;
|
||||||
|
|
||||||
|
let message: types::ServerMessage = serde_json::from_slice(message).unwrap();
|
||||||
|
|
||||||
|
println!("");
|
||||||
|
match message {
|
||||||
|
types::ServerMessage::GameState(state) => {
|
||||||
|
// println!("New game state");
|
||||||
|
let mut bot_msg = MsgBuffer::<bot_input::Owned>::new();
|
||||||
|
|
||||||
|
bot_msg.build(|b| {
|
||||||
|
b.set_input(&serde_json::to_vec(&state).unwrap());
|
||||||
|
});
|
||||||
|
handle.send_internal(bot_msg).display();
|
||||||
|
},
|
||||||
|
types::ServerMessage::FinalState(state) => {
|
||||||
|
println!("Game finished with");
|
||||||
|
println!("{:?}", state);
|
||||||
|
}
|
||||||
|
types::ServerMessage::PlayerAction(action) => {
|
||||||
|
println!("Out bot did");
|
||||||
|
println!("{:?}", action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BotLink;
|
||||||
|
impl BotLink {
|
||||||
|
fn params<C: Ctx>(foreign_id: ReactorId) -> LinkParams<Self, C> {
|
||||||
|
let mut params = LinkParams::new(foreign_id, Self);
|
||||||
|
|
||||||
|
params.external_handler(bot_return::Owned, CtxHandler::new(bot_return::e_to_i));
|
||||||
|
params.internal_handler(bot_input::Owned, CtxHandler::new(bot_input::i_to_e));
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RuntimeLink;
|
||||||
|
impl RuntimeLink {
|
||||||
|
fn params<C: Ctx>(foreign_id: ReactorId) -> LinkParams<Self, C> {
|
||||||
|
let mut params = LinkParams::new(foreign_id, Self);
|
||||||
|
|
||||||
|
params.external_handler(
|
||||||
|
actor_joined::Owned,
|
||||||
|
CtxHandler::new(actor_joined::e_to_i),
|
||||||
|
);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
69
client/src/types.rs
Normal file
69
client/src/types.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(tag = "type", content = "content")]
|
||||||
|
pub enum ServerMessage {
|
||||||
|
/// Game state in current turn
|
||||||
|
GameState(State),
|
||||||
|
/// The action that was performed
|
||||||
|
PlayerAction(PlayerAction),
|
||||||
|
/// The game is over, and this is the concluding state.
|
||||||
|
FinalState(State),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(tag = "type", content = "value")]
|
||||||
|
pub enum PlayerAction {
|
||||||
|
Timeout,
|
||||||
|
ParseError(String),
|
||||||
|
Commands(Vec<PlayerCommand>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PlayerCommand {
|
||||||
|
pub command: Command,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub error: Option<CommandError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum CommandError {
|
||||||
|
NotEnoughShips,
|
||||||
|
OriginNotOwned,
|
||||||
|
ZeroShipMove,
|
||||||
|
OriginDoesNotExist,
|
||||||
|
DestinationDoesNotExist,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Command {
|
||||||
|
pub origin: String,
|
||||||
|
pub destination: String,
|
||||||
|
pub ship_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct State {
|
||||||
|
pub planets: Vec<Planet>,
|
||||||
|
pub expeditions: Vec<Expedition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Expedition {
|
||||||
|
pub id: u64,
|
||||||
|
pub ship_count: u64,
|
||||||
|
pub origin: String,
|
||||||
|
pub destination: String,
|
||||||
|
pub owner: usize,
|
||||||
|
pub turns_remaining: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Planet {
|
||||||
|
pub ship_count: u64,
|
||||||
|
pub x: f64,
|
||||||
|
pub y: f64,
|
||||||
|
pub owner: Option<usize>,
|
||||||
|
pub name: String,
|
||||||
|
}
|
|
@ -1,31 +1,32 @@
|
||||||
import { Game } from "planetwars";
|
import { Game } from "planetwars";
|
||||||
import { memory } from "planetwars/plantwars_bg"
|
import { memory } from "planetwars/plantwars_bg"
|
||||||
|
import { Shader } from "./webgl/shader"
|
||||||
|
|
||||||
|
import { main } from './index.ts'
|
||||||
|
|
||||||
const URL = window.location.origin+window.location.pathname;
|
const URL = window.location.origin+window.location.pathname;
|
||||||
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
const LOCATION = URL.substring(0, URL.lastIndexOf("/") + 1);
|
||||||
|
|
||||||
const game_location = LOCATION + "static/game.json";
|
const game_location = LOCATION + "static/game.json";
|
||||||
|
|
||||||
// fetch(game_location)
|
fetch(game_location)
|
||||||
// .then((r) => r.text())
|
.then((r) => r.text())
|
||||||
// .then((response) => {
|
.then((response) => {
|
||||||
// console.log(response);
|
main(Game.new(response));
|
||||||
// let game = Game.new(response);
|
}).catch(console.error);
|
||||||
// console.log(game.turn_count());
|
|
||||||
// }).catch(console.error);
|
|
||||||
|
|
||||||
|
|
||||||
const g = Game.new("");
|
// const g = Game.new("");
|
||||||
|
|
||||||
const p1 = g.locations();
|
// const p1 = g.locations();
|
||||||
const s1 = g.location_count();
|
// const s1 = g.location_count();
|
||||||
console.log(p1, s1);
|
// console.log(p1, s1);
|
||||||
const a1 = new Float64Array(memory.buffer, p1, s1 * 3);
|
// const a1 = new Float64Array(memory.buffer, p1, s1 * 3);
|
||||||
console.log(a1);
|
// console.log(a1);
|
||||||
|
|
||||||
g.add_location(0.5, 1.2, 3.14);
|
// g.add_location(0.5, 1.2, 3.14);
|
||||||
|
|
||||||
const p2 = g.locations();
|
// const p2 = g.locations();
|
||||||
const s2 = g.location_count();
|
// const s2 = g.location_count();
|
||||||
const a2 = new Float64Array(memory.buffer, p2, s2 * 3);
|
// const a2 = new Float64Array(memory.buffer, p2, s2 * 3);
|
||||||
console.log(a2);
|
// console.log(a2);
|
||||||
|
|
5
frontend/www/index.ts
Normal file
5
frontend/www/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { Game } from "planetwars";
|
||||||
|
|
||||||
|
export function main(game: Game) {
|
||||||
|
console.log(game.turn_count());
|
||||||
|
}
|
79
frontend/www/package-lock.json
generated
79
frontend/www/package-lock.json
generated
|
@ -4063,6 +4063,12 @@
|
||||||
"sha.js": "^2.4.8"
|
"sha.js": "^2.4.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"picomatch": {
|
||||||
|
"version": "2.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz",
|
||||||
|
"integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"pify": {
|
"pify": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
|
@ -4094,8 +4100,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"planetwars": {
|
"planetwars": {
|
||||||
"version": "file:../pkg",
|
"version": "file:../pkg"
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"portfinder": {
|
"portfinder": {
|
||||||
"version": "1.0.21",
|
"version": "1.0.21",
|
||||||
|
@ -5192,6 +5197,70 @@
|
||||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ts-loader": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-7JedeOu2rsYHQDEr2fwmMozABwbQTZXEaEMZPSIWG7gpzRefOLJCqwdazcegHtyaxp04PeEgs/b0m08WMpnIzQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.3.0",
|
||||||
|
"enhanced-resolve": "^4.0.0",
|
||||||
|
"loader-utils": "^1.0.2",
|
||||||
|
"micromatch": "^4.0.0",
|
||||||
|
"semver": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"micromatch": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"braces": "^3.0.1",
|
||||||
|
"picomatch": "^2.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||||
|
@ -5220,6 +5289,12 @@
|
||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "3.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz",
|
||||||
|
"integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"union-value": {
|
"union-value": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "create-wasm-app",
|
"name": "create-wasm-app",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "create an app to consume rust-generated wasm packages",
|
"description": "create an app to consume rust-generated wasm packages",
|
||||||
"main": "index.js",
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --config webpack.config.js",
|
"build": "webpack --config webpack.config.js",
|
||||||
"start": "webpack-dev-server"
|
"start": "webpack-dev-server"
|
||||||
|
@ -18,6 +19,9 @@
|
||||||
"webpack",
|
"webpack",
|
||||||
"mozaic"
|
"mozaic"
|
||||||
],
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"planetwars": "file:../pkg"
|
||||||
|
},
|
||||||
"author": "Arthur Vercruysse <arthur.vercruysse@outlook.com>",
|
"author": "Arthur Vercruysse <arthur.vercruysse@outlook.com>",
|
||||||
"license": "(MIT OR Apache-2.0)",
|
"license": "(MIT OR Apache-2.0)",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -25,8 +29,9 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/ajuvercr/Planetwars#Readme",
|
"homepage": "https://github.com/ajuvercr/Planetwars#Readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"planetwars": "file:../pkg",
|
|
||||||
"webpack": "^4.29.3",
|
"webpack": "^4.29.3",
|
||||||
|
"ts-loader": "^6.0.2",
|
||||||
|
"typescript": "^3.5.2",
|
||||||
"webpack-cli": "^3.1.0",
|
"webpack-cli": "^3.1.0",
|
||||||
"webpack-dev-server": "^3.1.5",
|
"webpack-dev-server": "^3.1.5",
|
||||||
"copy-webpack-plugin": "^5.0.0"
|
"copy-webpack-plugin": "^5.0.0"
|
||||||
|
|
15
frontend/www/tsconfig.json
Normal file
15
frontend/www/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["es2017", "es7", "es6", "dom"],
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es6",
|
||||||
|
"jsx": "react",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
55
frontend/www/webgl/buffer.ts
Normal file
55
frontend/www/webgl/buffer.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
export class Buffer {
|
||||||
|
buffer: WebGLBuffer;
|
||||||
|
data: any;
|
||||||
|
count: number;
|
||||||
|
type: number;
|
||||||
|
|
||||||
|
constructor(gl: WebGLRenderingContext, data: number[], type: number) {
|
||||||
|
this.buffer = gl.createBuffer();
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
this.updateData(gl, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toArray(data: number[]): any {
|
||||||
|
return new Float32Array(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData(gl: WebGLRenderingContext, data: number[]) {
|
||||||
|
this.data = data;
|
||||||
|
this.count = data.length;
|
||||||
|
gl.bindBuffer(this.type, this.buffer);
|
||||||
|
gl.bufferData(this.type, this._toArray(data), gl.STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(gl: WebGLRenderingContext) {
|
||||||
|
gl.bindBuffer(this.type, this.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCount(): number {
|
||||||
|
return this.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VertexBuffer extends Buffer {
|
||||||
|
constructor(gl: WebGLRenderingContext, data: any) {
|
||||||
|
super(gl, data, gl.ARRAY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toArray(data: number[]): any {
|
||||||
|
return new Float32Array(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class IndexBuffer extends Buffer {
|
||||||
|
constructor(gl: WebGLRenderingContext, data: any) {
|
||||||
|
super(gl, data, gl.ELEMENT_ARRAY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
_toArray(data: number[]): any {
|
||||||
|
return new Uint16Array(data);
|
||||||
|
}
|
||||||
|
}
|
72
frontend/www/webgl/instance.ts
Normal file
72
frontend/www/webgl/instance.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { Renderable } from './renderer';
|
||||||
|
import { Shader, Uniform } from './shader';
|
||||||
|
import { Dictionary } from './util';
|
||||||
|
|
||||||
|
function createAndSetupTexture(gl: WebGLRenderingContext): WebGLTexture {
|
||||||
|
var texture = gl.createTexture();
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
// Set up texture so we can render any size image and so we are
|
||||||
|
// working with pixels.
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Foo implements Renderable {
|
||||||
|
stages: Stage[];
|
||||||
|
|
||||||
|
textures: WebGLTexture[];
|
||||||
|
framebuffers: WebGLFramebuffer[];
|
||||||
|
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
|
||||||
|
constructor(gl: WebGLRenderingContext, width: number, height: number) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
for (let ii = 0; ii < 2; ++ii) {
|
||||||
|
const texture = createAndSetupTexture(gl);
|
||||||
|
this.textures.push(texture);
|
||||||
|
|
||||||
|
// make the texture the same size as the image
|
||||||
|
gl.texImage2D(
|
||||||
|
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
|
||||||
|
gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||||
|
|
||||||
|
// Create a framebuffer
|
||||||
|
const fbo = gl.createFramebuffer();
|
||||||
|
this.framebuffers.push(fbo);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
|
// Attach a texture to it.
|
||||||
|
gl.framebufferTexture2D(
|
||||||
|
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(gl: WebGLRenderingContext) {
|
||||||
|
this.stages.forEach( (item, i) => {
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffers[i%2]);
|
||||||
|
item.render(gl);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.textures[i % 2]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Stage implements Renderable {
|
||||||
|
program: Shader;
|
||||||
|
uniforms: Dictionary<Uniform>;
|
||||||
|
|
||||||
|
render(gl: WebGLRenderingContext) {
|
||||||
|
this.program.bind(gl);
|
||||||
|
|
||||||
|
for (let name in this.uniforms) {
|
||||||
|
this.program.uniform(gl, name, this.uniforms[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
frontend/www/webgl/renderer.ts
Normal file
72
frontend/www/webgl/renderer.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
import { IndexBuffer } from './buffer';
|
||||||
|
import { Shader, Uniform1i } from './shader';
|
||||||
|
import { VertexArray } from './vertexBufferLayout';
|
||||||
|
import { Texture } from './texture';
|
||||||
|
|
||||||
|
export interface Renderable {
|
||||||
|
render(gl: WebGLRenderingContext): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Renderer {
|
||||||
|
renderables: Renderable[];
|
||||||
|
|
||||||
|
indexBuffers: IndexBuffer[];
|
||||||
|
vertexArrays: VertexArray[];
|
||||||
|
shaders: Shader[];
|
||||||
|
textures: Texture[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.indexBuffers = [];
|
||||||
|
this.vertexArrays = [];
|
||||||
|
this.shaders = [];
|
||||||
|
this.textures = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
addRenderable(item: Renderable) {
|
||||||
|
this.renderables.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
addToDraw(indexBuffer: IndexBuffer, vertexArray: VertexArray, shader: Shader, texture?: Texture): number {
|
||||||
|
this.indexBuffers.push(indexBuffer);
|
||||||
|
this.vertexArrays.push(vertexArray);
|
||||||
|
this.shaders.push(shader);
|
||||||
|
this.textures.push(texture);
|
||||||
|
|
||||||
|
return this.indexBuffers.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(gl: WebGLRenderingContext) {
|
||||||
|
const maxTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
||||||
|
let texLocation = 0;
|
||||||
|
|
||||||
|
for(let i = 0; i < this.indexBuffers.length; i ++) {
|
||||||
|
const indexBuffer = this.indexBuffers[i];
|
||||||
|
const vertexArray = this.vertexArrays[i];
|
||||||
|
const shader = this.shaders[i];
|
||||||
|
const texture = this.textures[i];
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
|
||||||
|
shader.uniform(gl, texture.name, new Uniform1i(texLocation));
|
||||||
|
texture.bind(gl, texLocation);
|
||||||
|
|
||||||
|
texLocation ++;
|
||||||
|
if (texLocation > maxTextures) {
|
||||||
|
console.error("Using too many textures, this is not supported yet\nUndefined behaviour!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertexArray && shader) {
|
||||||
|
vertexArray.bind(gl, shader);
|
||||||
|
|
||||||
|
if (indexBuffer) {
|
||||||
|
indexBuffer.bind(gl);
|
||||||
|
gl.drawElements(gl.TRIANGLES, indexBuffer.getCount(), gl.UNSIGNED_SHORT, 0);
|
||||||
|
} else {
|
||||||
|
console.error("IndexBuffer is required to render, for now");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
305
frontend/www/webgl/shader.ts
Normal file
305
frontend/www/webgl/shader.ts
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
import { Dictionary } from './util';
|
||||||
|
|
||||||
|
function error(msg: string) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultShaderType = [
|
||||||
|
"VERTEX_SHADER",
|
||||||
|
"FRAGMENT_SHADER"
|
||||||
|
];
|
||||||
|
|
||||||
|
function loadShader(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
shaderSource: string,
|
||||||
|
shaderType: number,
|
||||||
|
opt_errorCallback: any,
|
||||||
|
): WebGLShader {
|
||||||
|
var errFn = opt_errorCallback || error;
|
||||||
|
// Create the shader object
|
||||||
|
var shader = gl.createShader(shaderType);
|
||||||
|
|
||||||
|
// Load the shader source
|
||||||
|
gl.shaderSource(shader, shaderSource);
|
||||||
|
|
||||||
|
// Compile the shader
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
// Check the compile status
|
||||||
|
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||||
|
if (!compiled) {
|
||||||
|
// Something went wrong during compilation; get the error
|
||||||
|
var lastError = gl.getShaderInfoLog(shader);
|
||||||
|
errFn("*** Error compiling shader '" + shader + "':" + lastError);
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("created shader with source");
|
||||||
|
console.log(shaderSource);
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProgram(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
shaders: WebGLShader[],
|
||||||
|
opt_attribs: string[],
|
||||||
|
opt_locations: number[],
|
||||||
|
opt_errorCallback: any,
|
||||||
|
): WebGLProgram {
|
||||||
|
var errFn = opt_errorCallback || error;
|
||||||
|
var program = gl.createProgram();
|
||||||
|
shaders.forEach(function (shader) {
|
||||||
|
gl.attachShader(program, shader);
|
||||||
|
});
|
||||||
|
if (opt_attribs) {
|
||||||
|
opt_attribs.forEach(function (attrib, ndx) {
|
||||||
|
gl.bindAttribLocation(
|
||||||
|
program,
|
||||||
|
opt_locations ? opt_locations[ndx] : ndx,
|
||||||
|
attrib);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
// Check the link status
|
||||||
|
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||||
|
if (!linked) {
|
||||||
|
// something went wrong with the link
|
||||||
|
var lastError = gl.getProgramInfoLog(program);
|
||||||
|
errFn("Error in program linking:" + lastError);
|
||||||
|
|
||||||
|
gl.deleteProgram(program);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createShaderFromScript(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
scriptId: string,
|
||||||
|
context: Dictionary<any>,
|
||||||
|
opt_shaderType: number,
|
||||||
|
opt_errorCallback: any,
|
||||||
|
): WebGLShader {
|
||||||
|
var shaderSource = "";
|
||||||
|
var shaderType;
|
||||||
|
var shaderScript = document.getElementById(scriptId) as HTMLScriptElement;
|
||||||
|
if (!shaderScript) {
|
||||||
|
console.log("*** Error: unknown script element" + scriptId);
|
||||||
|
}
|
||||||
|
shaderSource = shaderScript.text;
|
||||||
|
|
||||||
|
for (let key in context) {
|
||||||
|
console.log("substitute " + key);
|
||||||
|
shaderSource = shaderSource.replace(new RegExp("\\$" + key, 'g'), context[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opt_shaderType) {
|
||||||
|
if (shaderScript.type === "x-shader/x-vertex") {
|
||||||
|
shaderType = 35633;
|
||||||
|
} else if (shaderScript.type === "x-shader/x-fragment") {
|
||||||
|
shaderType = 35632;
|
||||||
|
} else if (shaderType !== gl.VERTEX_SHADER && shaderType !== gl.FRAGMENT_SHADER) {
|
||||||
|
console.log("*** Error: unknown shader type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadShader(
|
||||||
|
gl, shaderSource, opt_shaderType ? opt_shaderType : shaderType,
|
||||||
|
opt_errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Shader {
|
||||||
|
shader: WebGLProgram;
|
||||||
|
uniformCache: Dictionary<WebGLUniformLocation>;
|
||||||
|
attribCache: Dictionary<number>;
|
||||||
|
|
||||||
|
static createProgramFromScripts(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
shaderScriptIds: string[],
|
||||||
|
context = {},
|
||||||
|
opt_attribs?: string[],
|
||||||
|
opt_locations?: number[],
|
||||||
|
opt_errorCallback?: any,
|
||||||
|
): Shader {
|
||||||
|
var shaders = [];
|
||||||
|
for (var ii = 0; ii < shaderScriptIds.length; ++ii) {
|
||||||
|
shaders.push(createShaderFromScript(
|
||||||
|
gl, shaderScriptIds[ii], context, (gl as any)[defaultShaderType[ii % 2]] as number, opt_errorCallback));
|
||||||
|
}
|
||||||
|
return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createProgramFromUrls(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
vert_url: string,
|
||||||
|
frag_url: string,
|
||||||
|
context?: Dictionary<string>,
|
||||||
|
opt_attribs?: string[],
|
||||||
|
opt_locations?: number[],
|
||||||
|
opt_errorCallback?: any,
|
||||||
|
): Promise<Shader> {
|
||||||
|
const sources = (await Promise.all([
|
||||||
|
fetch(vert_url).then((r) => r.text()),
|
||||||
|
fetch(frag_url).then((r) => r.text()),
|
||||||
|
])).map(x => {
|
||||||
|
for (let key in context) {
|
||||||
|
x = x.replace(new RegExp("\\$" + key, 'g'), context[key]);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
|
||||||
|
const shaders = [
|
||||||
|
loadShader(gl, sources[0], 35633, opt_errorCallback),
|
||||||
|
loadShader(gl, sources[1], 35632, opt_errorCallback),
|
||||||
|
];
|
||||||
|
return new Shader(createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(shader: WebGLProgram) {
|
||||||
|
this.shader = shader;
|
||||||
|
this.uniformCache = {};
|
||||||
|
this.attribCache = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(gl: WebGLRenderingContext) {
|
||||||
|
gl.useProgram(this.shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different locations have different types :/
|
||||||
|
getUniformLocation(gl: WebGLRenderingContext, name: string): WebGLUniformLocation {
|
||||||
|
if (this.uniformCache[name] === undefined) {
|
||||||
|
this.uniformCache[name] = gl.getUniformLocation(this.shader, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.uniformCache[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
getAttribLocation(gl: WebGLRenderingContext, name: string): number {
|
||||||
|
if (this.attribCache[name] === undefined) {
|
||||||
|
this.attribCache[name] = gl.getAttribLocation(this.shader, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.attribCache[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform<T extends Uniform>(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
name: string,
|
||||||
|
uniform: T,
|
||||||
|
) {
|
||||||
|
this.bind(gl);
|
||||||
|
const location = this.getUniformLocation(gl, name);
|
||||||
|
if (location < 0) {
|
||||||
|
console.log("No location found with name " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform.setUniform(gl, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Uniform {
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform2fv implements Uniform {
|
||||||
|
data: number[];
|
||||||
|
constructor(data: number[]) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform2fv(location, this.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform3fv implements Uniform {
|
||||||
|
data: number[];
|
||||||
|
constructor(data: number[]) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform3fv(location, this.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform1iv implements Uniform {
|
||||||
|
data: number[];
|
||||||
|
constructor(data: number[]) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform1iv(location, this.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform1i implements Uniform {
|
||||||
|
texture: number;
|
||||||
|
|
||||||
|
constructor(texture: number) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform1i(location, this.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform1f implements Uniform {
|
||||||
|
texture: number;
|
||||||
|
|
||||||
|
constructor(texture: number) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform1f(location, this.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform2f implements Uniform {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
|
||||||
|
constructor(x: number, y: number) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform2f(location, this.x, this.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Uniform4f implements Uniform {
|
||||||
|
v0: number;
|
||||||
|
v1: number;
|
||||||
|
v2: number;
|
||||||
|
v3: number;
|
||||||
|
|
||||||
|
constructor(vec: number[]) {
|
||||||
|
this.v0 = vec[0];
|
||||||
|
this.v1 = vec[1];
|
||||||
|
this.v2 = vec[2];
|
||||||
|
this.v3 = vec[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniform4f(location, this.v0, this.v1, this.v2, this.v3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UniformMatrix3fv implements Uniform {
|
||||||
|
data: number[];
|
||||||
|
constructor(data: number[]) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniform(gl: WebGLRenderingContext, location: WebGLUniformLocation) {
|
||||||
|
gl.uniformMatrix3fv(location, false, this.data);
|
||||||
|
}
|
||||||
|
}
|
68
frontend/www/webgl/texture.ts
Normal file
68
frontend/www/webgl/texture.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: fix texture locations, not use only 0
|
||||||
|
export class Texture {
|
||||||
|
texture: WebGLTexture;
|
||||||
|
image: HTMLImageElement;
|
||||||
|
loaded: boolean;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
gl: WebGLRenderingContext,
|
||||||
|
path: string,
|
||||||
|
name: string,
|
||||||
|
) {
|
||||||
|
this.loaded = false;
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
this.image = new Image();
|
||||||
|
this.image.onload = () => this.handleImageLoaded(gl);
|
||||||
|
this.image.onerror = error;
|
||||||
|
this.image.src = path;
|
||||||
|
|
||||||
|
this.texture = gl.createTexture();
|
||||||
|
this.bind(gl);
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA,
|
||||||
|
gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleImageLoaded(gl: WebGLRenderingContext) {
|
||||||
|
console.log('handling image loaded');
|
||||||
|
this.bind(gl);
|
||||||
|
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image);
|
||||||
|
|
||||||
|
this.unbind(gl);
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(gl: WebGLRenderingContext, location=0) {
|
||||||
|
gl.activeTexture(gl.TEXTURE0 + location);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind(gl: WebGLRenderingContext) {
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getWidth(): number {
|
||||||
|
return this.image.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHeight(): number {
|
||||||
|
return this.image.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(e: any) {
|
||||||
|
console.error("IMAGE LOAD ERROR");
|
||||||
|
console.error(e);
|
||||||
|
}
|
129
frontend/www/webgl/util.ts
Normal file
129
frontend/www/webgl/util.ts
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
|
||||||
|
export interface Dictionary<T> {
|
||||||
|
[Key: string]: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface OnLoadable {
|
||||||
|
onload: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onload2promise<T extends OnLoadable>(obj: T): Promise<T> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
obj.onload = () => resolve(obj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resizeCanvasToDisplaySize(
|
||||||
|
canvas: HTMLCanvasElement,
|
||||||
|
multiplier?: number,
|
||||||
|
): boolean {
|
||||||
|
multiplier = multiplier || 1;
|
||||||
|
var width = canvas.clientWidth * multiplier | 0;
|
||||||
|
var height = canvas.clientHeight * multiplier | 0;
|
||||||
|
if (canvas.width !== width || canvas.height !== height) {
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FPSCounter {
|
||||||
|
last: number;
|
||||||
|
count: number;
|
||||||
|
constructor() {
|
||||||
|
this.last = 0;
|
||||||
|
this.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame(now: number) {
|
||||||
|
this.count += 1;
|
||||||
|
if (now - this.last > 1) {
|
||||||
|
this.last = now;
|
||||||
|
console.log(this.count + " fps");
|
||||||
|
this.count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class M3 {
|
||||||
|
_data: any;
|
||||||
|
|
||||||
|
constructor(data: any) {
|
||||||
|
this._data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ident(): M3 {
|
||||||
|
return new M3([
|
||||||
|
1, 0, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(other: M3): M3 {
|
||||||
|
const a = this._data;
|
||||||
|
const b = other._data;
|
||||||
|
|
||||||
|
var a00 = a[0 * 3 + 0];
|
||||||
|
var a01 = a[0 * 3 + 1];
|
||||||
|
var a02 = a[0 * 3 + 2];
|
||||||
|
var a10 = a[1 * 3 + 0];
|
||||||
|
var a11 = a[1 * 3 + 1];
|
||||||
|
var a12 = a[1 * 3 + 2];
|
||||||
|
var a20 = a[2 * 3 + 0];
|
||||||
|
var a21 = a[2 * 3 + 1];
|
||||||
|
var a22 = a[2 * 3 + 2];
|
||||||
|
var b00 = b[0 * 3 + 0];
|
||||||
|
var b01 = b[0 * 3 + 1];
|
||||||
|
var b02 = b[0 * 3 + 2];
|
||||||
|
var b10 = b[1 * 3 + 0];
|
||||||
|
var b11 = b[1 * 3 + 1];
|
||||||
|
var b12 = b[1 * 3 + 2];
|
||||||
|
var b20 = b[2 * 3 + 0];
|
||||||
|
var b21 = b[2 * 3 + 1];
|
||||||
|
var b22 = b[2 * 3 + 2];
|
||||||
|
|
||||||
|
return new M3([
|
||||||
|
b00 * a00 + b01 * a10 + b02 * a20,
|
||||||
|
b00 * a01 + b01 * a11 + b02 * a21,
|
||||||
|
b00 * a02 + b01 * a12 + b02 * a22,
|
||||||
|
b10 * a00 + b11 * a10 + b12 * a20,
|
||||||
|
b10 * a01 + b11 * a11 + b12 * a21,
|
||||||
|
b10 * a02 + b11 * a12 + b12 * a22,
|
||||||
|
b20 * a00 + b21 * a10 + b22 * a20,
|
||||||
|
b20 * a01 + b21 * a11 + b22 * a21,
|
||||||
|
b20 * a02 + b21 * a12 + b22 * a22,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
translation(x: number, y: number): M3 {
|
||||||
|
const out = [...this._data];
|
||||||
|
out[6] += x;
|
||||||
|
out[7] += y;
|
||||||
|
return new M3(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate(rad: number): M3 {
|
||||||
|
var c = Math.cos(rad);
|
||||||
|
var s = Math.sin(rad);
|
||||||
|
|
||||||
|
const out = new M3([...this._data]);
|
||||||
|
|
||||||
|
return out.multiply(new M3([
|
||||||
|
c, -s, 0,
|
||||||
|
s, c, 0,
|
||||||
|
0, 0, 1
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
scale(s_x: number, s_y = s_x, s_z = 1): M3 {
|
||||||
|
const out = new M3([...this._data]);
|
||||||
|
return out.multiply(new M3([
|
||||||
|
s_x, 0, 0,
|
||||||
|
0, s_y, 0,
|
||||||
|
0, 0, s_z,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
0
frontend/www/webgl/vertexArray.ts
Normal file
0
frontend/www/webgl/vertexArray.ts
Normal file
112
frontend/www/webgl/vertexBufferLayout.ts
Normal file
112
frontend/www/webgl/vertexBufferLayout.ts
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import { Buffer, VertexBuffer } from './buffer';
|
||||||
|
import { Shader } from './shader';
|
||||||
|
|
||||||
|
export class VertexBufferElement {
|
||||||
|
type: number;
|
||||||
|
amount: number;
|
||||||
|
type_size: number;
|
||||||
|
normalized: boolean;
|
||||||
|
index: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
type: number,
|
||||||
|
amount: number,
|
||||||
|
type_size: number,
|
||||||
|
index: string,
|
||||||
|
normalized: boolean,
|
||||||
|
) {
|
||||||
|
this.type = type;
|
||||||
|
this.amount = amount;
|
||||||
|
this.type_size = type_size;
|
||||||
|
this.normalized = normalized;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VertexBufferLayout {
|
||||||
|
elements: VertexBufferElement[];
|
||||||
|
stride: number;
|
||||||
|
offset: number;
|
||||||
|
|
||||||
|
constructor(offset = 0) {
|
||||||
|
this.elements = [];
|
||||||
|
this.stride = 0;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe wrong normalized type
|
||||||
|
push(
|
||||||
|
type: number,
|
||||||
|
amount: number,
|
||||||
|
type_size: number,
|
||||||
|
index: string,
|
||||||
|
normalized = false,
|
||||||
|
) {
|
||||||
|
this.elements.push(new VertexBufferElement(type, amount, type_size, index, normalized));
|
||||||
|
this.stride += amount * type_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
getElements(): VertexBufferElement[] {
|
||||||
|
return this.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStride(): number {
|
||||||
|
return this.stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// glEnableVertexAttribArray is to specify what location of the current program the follow data is needed
|
||||||
|
// glVertexAttribPointer tells gl that that data is at which location in the supplied data
|
||||||
|
export class VertexArray {
|
||||||
|
// There is no renderer ID, always at bind buffers and use glVertexAttribPointer
|
||||||
|
buffers: Buffer[];
|
||||||
|
layouts: VertexBufferLayout[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.buffers = [];
|
||||||
|
this.layouts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
addBuffer(vb: VertexBuffer, layout: VertexBufferLayout) {
|
||||||
|
this.buffers.push(vb);
|
||||||
|
this.layouts.push(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bind buffers providing program data
|
||||||
|
bind(gl: WebGLRenderingContext, shader: Shader) {
|
||||||
|
shader.bind(gl);
|
||||||
|
for(let i = 0; i < this.buffers.length; i ++) {
|
||||||
|
const buffer = this.buffers[i];
|
||||||
|
const layout = this.layouts[i];
|
||||||
|
|
||||||
|
buffer.bind(gl);
|
||||||
|
const elements = layout.getElements();
|
||||||
|
let offset = layout.offset;
|
||||||
|
|
||||||
|
for (let j = 0; j < elements.length; j ++) {
|
||||||
|
const element = elements[j];
|
||||||
|
const location = shader.getAttribLocation(gl, element.index);
|
||||||
|
|
||||||
|
if (location >= 0) {
|
||||||
|
gl.enableVertexAttribArray(location);
|
||||||
|
gl.vertexAttribPointer(
|
||||||
|
location, element.amount, element.type,
|
||||||
|
element.normalized, layout.stride, offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += element.amount * element.type_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Undo bind operation
|
||||||
|
unbind(gl: WebGLRenderingContext) {
|
||||||
|
this.layouts.forEach((layout) => {
|
||||||
|
layout.getElements().forEach((_, index) => {
|
||||||
|
gl.disableVertexAttribArray(index);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,12 +2,24 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: "./bootstrap.js",
|
mode: 'development',
|
||||||
output: {
|
entry: './bootstrap.js',
|
||||||
path: path.resolve(__dirname, "dist"),
|
module: {
|
||||||
filename: "bootstrap.js",
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [ '.tsx', '.ts', '.js', '.wasm' ]
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: 'bootstrap.js',
|
||||||
|
path: path.resolve(__dirname, 'dist')
|
||||||
},
|
},
|
||||||
mode: "development",
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new CopyWebpackPlugin(['index.html'])
|
new CopyWebpackPlugin(['index.html'])
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue