Skip to content

Commit

Permalink
Merge pull request #170 from xaya/fork
Browse files Browse the repository at this point in the history
Implement "unblock spawns" fork
  • Loading branch information
domob1812 authored Sep 3, 2020
2 parents 3bf5cbb + 691d230 commit fdc9f67
Show file tree
Hide file tree
Showing 35 changed files with 1,086 additions and 212 deletions.
1 change: 1 addition & 0 deletions gametest/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ REGTESTS = \
damage_lists.py \
fame.py \
findpath.py \
fork_unblockspawns.py \
getbuildingshape.py \
getserviceinfo.py \
getregionat.py \
Expand Down
106 changes: 63 additions & 43 deletions gametest/findpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ def finish (self):

class FindPathTest (PXTest):

def call (self, source, target, l1range, faction="r", exbuildings=[]):
def call (self, source, target, l1range,
faction="r", exbuildings=[], height=0):
return self.rpc.game.findpath (source=source, target=target,
faction=faction, l1range=l1range,
exbuildings=exbuildings)
exbuildings=exbuildings, height=height)

def strip (self, val):
"""
Expand Down Expand Up @@ -136,7 +137,8 @@ def run (self):

self.testExbuildings ()
self.testInvalidData ()
self.testWithData ()
self.testWithCharacterData ()
self.testWithBuildingData ()

def testExbuildings (self):
self.mainLogger.info ("Testing exbuildings...")
Expand Down Expand Up @@ -209,17 +211,59 @@ def testInvalidData (self):
[{"faction": "a", "position": coord}],
[{"faction": "r", "position": "foo"}],
[{"faction": "r", "position": {"x": 1}}],
[
{"faction": "r", "position": coord},
{"faction": "r", "position": coord},
],
]:
self.expectError (-1, "characters is invalid",
self.rpc.game.setpathdata,
buildings=[], characters=specs)

def testWithData (self):
self.mainLogger.info ("Testing with set data...")
def testWithCharacterData (self):
self.mainLogger.info ("Testing with character data...")

# Create some test characters that we can use as obstacles.
self.initAccount ("red", "r")
self.initAccount ("green", "g")
self.generate (1)
self.createCharacters ("red", 2)
self.createCharacters ("green")
self.generate (1)

# Place some characters on the map. We then use the output of
# getcharacters to pass as findpath data, to ensure this works.
self.moveCharactersTo ({
"red": {"x": 0, "y": 0},
"green": {"x": 10, "y": 0},
"red 2": {"x": 0, "y": 10},
})
characters = self.getRpc ("getcharacters")
self.rpc.game.setpathdata (buildings=[], characters=characters)

moreArgs = {
"source": {"x": 0, "y": 0},
"faction": "r",
"l1range": 8000,
}

moreArgs["height"] = 0
self.assertEqual (self.call (target={"x": 20, "y": 0}, **moreArgs)["dist"],
20000)
self.assertEqual (self.call (target={"x": 0, "y": 20}, **moreArgs)["dist"],
21000)
self.expectError (1, "no connection",
self.call,
target={"x": 0, "y": 10}, **moreArgs)

moreArgs["height"] = 500
self.assertEqual (self.call (target={"x": 20, "y": 0}, **moreArgs)["dist"],
21000)
self.assertEqual (self.call (target={"x": 0, "y": 20}, **moreArgs)["dist"],
21000)
self.assertEqual (self.call (target={"x": 10, "y": 0}, **moreArgs)["dist"],
17000)
self.assertEqual (self.call (target={"x": 0, "y": 10}, **moreArgs)["dist"],
17000)

def testWithBuildingData (self):
self.mainLogger.info ("Testing with building data...")

# This is a very long path, which takes a non-negligible amount of time
# to compute. We use this later to ensure that multiple calls are
Expand All @@ -232,6 +276,7 @@ def testWithData (self):
"faction": "r",
"l1range": 8000,
"exbuildings": [],
"height": 0,
}
before = time.clock_gettime (time.CLOCK_MONOTONIC)
path = self.call (**kwargs)
Expand All @@ -247,57 +292,32 @@ def testWithData (self):
serialised = json.dumps (path["wp"], separators=(",", ":"))
assert len (serialised) > 3000

# Create some test characters that we can use as obstacles.
self.initAccount ("red", "r")
self.initAccount ("green", "g")
self.generate (1)
self.createCharacters ("red", 3)
self.createCharacters ("green")

# Now place buildings and characters in two steps on the map, which make
# the path from longA to longB further. We use the outputs of getbuildings
# and getcharacters itself, to ensure that it can be passed directly back
# to setpathdata.
# Now place buildings in two steps on the map, which make the path from
# longA to longB further. We use the outputs of getbuildings itself, to
# ensure that it can be passed directly back to setpathdata.
buildings = [[]]
characters = [[]]

self.build ("r rt", None,
offsetCoord (longA, {"x": 1, "y": 0}, False), rot=0)
self.build ("r rt", None,
offsetCoord (longA, {"x": 1, "y": -1}, False), rot=0)
self.build ("r rt", None,
offsetCoord (longA, {"x": 0, "y": 1}, False), rot=0)
self.moveCharactersTo ({
"red": longA,
"red 2": offsetCoord (longA, {"x": 1, "y": 0}, False),
})
bIds = [
b["id"]
for b in self.getRpc ("getbuildings")
if b["type"] == "r rt"
]
self.getCharacters ()["red"].sendMove ({"eb": bIds[0]})
self.generate (1)
self.assertEqual (self.getCharacters ()["red"].isInBuilding (), True)

buildings.append (self.getRpc ("getbuildings"))
characters.append (self.getRpc ("getcharacters"))

self.build ("r rt", None,
offsetCoord (longA, {"x": 0, "y": -1}, False), rot=0)
self.moveCharactersTo ({
"red 3": offsetCoord (longA, {"x": -1, "y": 1}, False),
"green": offsetCoord (longA, {"x": -1, "y": 0}, False),
})

self.build ("r rt", None,
offsetCoord (longA, {"x": -1, "y": 1}, False), rot=0)
buildings.append (self.getRpc ("getbuildings"))
characters.append (self.getRpc ("getcharacters"))

# We do three calls now in parallel, with different sets of buildings.
# All should be running concurrently and not block each other. The total
# time should be shorter than sequential execution.
before = time.clock_gettime (time.CLOCK_MONOTONIC)
calls = []
for b, c in zip (buildings, characters):
calls.append (AsyncFindPath (self.gamenode, b, c, **kwargs))
for b in buildings:
calls.append (AsyncFindPath (self.gamenode, b, [], **kwargs))
[shortLen, midLen, longLen] = [c.finish ()["dist"] for c in calls]
after = time.clock_gettime (time.CLOCK_MONOTONIC)
threeDuration = after - before
Expand Down
83 changes: 83 additions & 0 deletions gametest/fork_unblockspawns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3

# GSP for the Taurion blockchain game
# Copyright (C) 2020 Autonomous Worlds Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

"""
Integration test the "unblock spawns" fork.
"""

from pxtest import PXTest

FORK_HEIGHT = 500


class UnblockSpawnsForkTest (PXTest):

def run (self):
self.collectPremine ()
self.splitPremine ()

self.initAccount ("red", "r")
self.initAccount ("green", "g")
self.initAccount ("blue", "b")
self.generate (1)

# Remember a block before the fork is active, which we will later
# reorg to and check that the fork is then still inactive.
self.generate (100)
reorgBlock = self.rpc.xaya.getbestblockhash ()

# Advance until almost the fork height.
self.advanceToHeight (FORK_HEIGHT - 2)

self.mainLogger.info ("Creating characters before the fork...")
for nm in ["red", "green", "blue"]:
self.createCharacters (nm)
self.generate (1)
chars = self.getCharacters ()
for nm in ["red", "green", "blue"]:
self.assertEqual (chars[nm].isInBuilding (), False)

self.mainLogger.info ("Creating characters after the fork...")
for nm in ["red", "green", "blue"]:
self.createCharacters (nm)
self.generate (1)
self.assertEqual (self.rpc.xaya.getblockcount (), FORK_HEIGHT)
chars = self.getCharacters ()
buildings = self.getBuildings ()
for nm, t in [("red", "r ss"), ("green", "g ss"), ("blue", "b ss")]:
c = chars["%s 2" % nm]
self.assertEqual (c.isInBuilding (), True)
self.assertEqual (buildings[c.getBuildingId ()].getType (), t)

# Test a reorg back to before the fork.
self.mainLogger.info ("Testing reorg to before the fork...")
oldState = self.getGameState ()

self.rpc.xaya.invalidateblock (reorgBlock)
self.initAccount ("reorg", "r")
self.generate (1)
self.createCharacters ("reorg")
self.generate (1)
self.assertEqual (self.getCharacters ()["reorg"].isInBuilding (), False)

self.rpc.xaya.reconsiderblock (reorgBlock)
self.expectGameState (oldState)


if __name__ == "__main__":
UnblockSpawnsForkTest ().main ()
2 changes: 0 additions & 2 deletions gametest/godmode.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def run (self):
self.createCharacters ("domob")
self.generate (1)
c = self.getCharacters ()["domob"]
pos = c.getPosition ()
charIdStr = c.getIdStr ()

self.mainLogger.info ("Testing build...")
Expand Down Expand Up @@ -94,7 +93,6 @@ def run (self):

self.mainLogger.info ("Testing teleport...")
target = {"x": 28, "y": 9}
assert pos != target
self.adminCommand ({"god": {"teleport": {charIdStr: target}}})
self.generate (1)
self.assertEqual (self.getCharacters ()["domob"].getPosition (), target)
Expand Down
Loading

0 comments on commit fdc9f67

Please sign in to comment.