Discussion: Contract system
-
I really like this system- especially the custom part of it. I can see how this could be used for a number of things people have done manually, such as @Bovius paying players to build his art (and he even wrote scripts for them, so this would be a perfect tie in) or the "clear the edge" folks paying people to remove their rooms in specific sectors.
I do think it would be possible to build a system that would also allow completely automated codebases to contribute (although I also agree that there's no way to completely automate this that wouldn't either be burdensome to the game admins or limiting on the community).
You mentioned that a standardized list of contract templates would be more powerful and flexible when guided by the community, but for things to be completely automated there needs to be a way to verify that the code matches what the players expect. I think this can be done by making it so players can publish contract templates that other players can use. Then people can choose to trust a specific players public contracts when used by other players. For example, the
LeagueOfAutomatedNations
account could publish contracts from a repository on github. Players could then be reasonably sure that the contracts on the site that are "written by"LeagueOfAutomatedNations
are what they expect (and the first time it gets abused everyone will stop trusting it and start trusting something else).
-
@w4rl0ck said in Discussion: Contract system:
for example spawning creeps... people have different ways to queue creeps to spawn.
The example they used shows how to handle this- let them spawn what's needed and have your code search for creeps that have a specific memory value. Still, it might be a good idea to give the contract an api a way to expose desired creep builds.
@w4rl0ck said in Discussion: Contract system:
You can't enforce people to fulfill the contract anyways .. of course you can prevent the user to pause the code .. but you can't stop him to change memory of the contractor creeps, suiciding creeps or other more subtile sabotage like changing prototypes so the script won't work correctly.
Presumably the contract would have a way to say that it's "satisfied". If the contract involved building a spawn, but the player accepts the contract and somehow sabotages it then the spawn never gets built and the contract keeps running.
Presumably all the other issues could be resolved by allowing the person who took the contract on to cancel it without getting paid.
-
@artch So a contract can consist of multiple modules which will simply run in the context of another player?
A contract doesn't consist of multiple modules, it's just one long string of code, but yes, it is executed in the contractor's context.
Even with this functionality, which is awesome by the way, this won't solve the problem of reusing the same code for multiple contracts.
What is the problem here exactly?
-
@w4rl0ck My only concern of what you have mentioned is modifying prototypes. We're still debating on how to handle that. All other things could (and should) be covered by contract conditions.
-
@artch said in Discussion: Contract system:
Even with this functionality, which is awesome by the way, this won't solve the problem of reusing the same code for multiple contracts.
What is the problem here exactly?
Taking your example from above, if someone wants to setup two contracts for different
sourceId
s, he will have to copy the module's code and change the constant's value for each of them. It doesn't make any sense to copy an entire file just to change a single value. This would not only be bad coding practice (DRY), it would be impossible or at least impractical to automate.
-
I have a couple of questions/concerns here:
Terminology: Client=Guy paying $$$, Contractor=Guy doing work.
- Is the code for a contract proposed by the contractor, or by the client?
Can be both. Code is proposed by the party creating the offer, and an offer can be created by any party. When you create an offer, you write code and choose one of two options:
- I am the client (I pay)
- I am the contractor (I execute the code)
- Is the client able to cancel his contract?
Yes.
If so, does the contractor get paid in any way when the client cancels?
I think that would make sense.
- If a contractor is locked-in to a contract, and is unable to edit it, what happens if there is a bug that makes the contract unsatisfiable? Is the contractor doomed to waste CPU on a fruitless contract forever? In this case, I doubt that any rational person would ever accept a contract. It would make far more sense to me to allow players to break contracts (potentially with some kind of penalty system, such as credits kept in escrow or similar).
Yes, both parties are able to break the contract on some terms.
- What happens if the contractor runs out of CPU on a tick or encounters an error? Is the contract code still executed?
No, all your contracts won't be executed on this tick.
- What if a contract throws an exception? How is this handled?
It is handled as usual, you will see an error in your console.
-
You mentioned that a standardized list of contract templates would be more powerful and flexible when guided by the community, but for things to be completely automated there needs to be a way to verify that the code matches what the players expect. I think this can be done by making it so players can publish contract templates that other players can use. Then people can choose to trust a specific players public contracts when used by other players. For example, the
LeagueOfAutomatedNations
account could publish contracts from a repository on github. Players could then be reasonably sure that the contracts on the site that are "written by"LeagueOfAutomatedNations
are what they expect (and the first time it gets abused everyone will stop trusting it and start trusting something else).While I admit it sounds interesting and cool in theory, but implementing this is a lot of work, and I doubt very much that even a single deal using such a template-based automated convention will ever be made even once by anyone at all. Some people here express the opinion this entire mechanic will be used by 5 people, and automated variant of it will be used by literally nobody.
-
Taking your example from above, if someone wants to setup two contracts for different
sourceId
s, he will have to copy the module's code and change the constant's value for each of them. It doesn't make any sense to copy an entire file just to change a single value. This would not only be bad coding practice (DRY), it would be impossible or at least impractical to automate.Oh, I see. Well, it's just how the system works basically - every contract consists of some code. You can use an external template (e.g. from GitHub) to create that code, but essentialy it will be a separate script in the database. In the same way as how we have a lot of players running identical open source code base - it's also suboptimal, but it is how it works.
-
@artch said in Discussion: Contract system:
Taking your example from above, if someone wants to setup two contracts for different
sourceId
s, he will have to copy the module's code and change the constant's value for each of them. It doesn't make any sense to copy an entire file just to change a single value. This would not only be bad coding practice (DRY), it would be impossible or at least impractical to automate.Oh, I see. Well, it's just how the system works basically - every contract consists of some code. You can use an external template (e.g. from GitHub) to create that code, but essentialy it will be a separate script in the database. In the same way as how we have a lot of players running identical open source code base - it's also suboptimal, but it is how it works.
When two independent players want to use the same contract template that's an entirely different story and saving the contracts separately in the database once they've been created is absolutely fine.
Would you be open to accept pull requests to add some sort of parameter/environment variable/contract memory when the feature is actually added to the game?
This would also make automatic accepting of contracts a lot easier, add a checksum of the module to the contract and let your code decide whether it wants to accept it or not based on the parameters. This will only work for "well written" contract code, but that's something we as the community are responsible for.
-
@postcrafter We won't have API for automatic contracts acceptance/creation, so environment variables don't make a lot of difference. And such a PR would require access to the official driver code which is not open sourced, and is much more sophisticated than the private server driver.
-
@artch said in Discussion: Contract system:
While I admit it sounds interesting and cool in theory, but implementing this is a lot of work, and I doubt very much that even a single deal using such a template-based automated convention will ever be made even once by anyone at all. Some people here express the opinion this entire mechanic will be used by 5 people, and automated variant of it will be used by literally nobody.
I actually think having the "standard library" of player contracts will make it more likely to get used, not less.
Let's use the
LeagueOfAutomatedNations
example. Assuming the system is workable, I would create templates for the following-Build Spawn in Room
Destroy Structure in Room
Guard Portal
Then players who want to make extra credits already have tasks that they can easily consume. Players could program the specifics for each bootstrapping each contract type once then scan for any players that are requesting them, rather than having to do a bunch of manual work and potentially having to write custom code for each project. People would still have the option of writing the more advanced/unique stuff, and since people would be able to get used to the system using the more "standard" stuff there could be more people willing to dive into those.
I admit I could be wrong about this, but really think some system for standard contracts and identifying when they're in use would make the system more popular simply because it would make it easier for people to use it (assuming the community put the work into making the scripts, which I think is a reasonable assumption).
-
There are probably other ways these same goals could be accomplished in different ways too. Another idea would be to separate out parameters (json blob defined by client) from code, and then give each code a unique signature when it's updated (SHA512?) that people can compare against to confirm it's the script they think it is.
-
@artch said in Discussion: Contract system:
@postcrafter We won't have API for automatic contracts acceptance/creation, so environment variables don't make a lot of difference.
I seem to have missed that part about no automatic creation and acceptance of contracts earlier. Unfortunately this makes it a non-feature for me, I think you do at least need to be able to create contracts automatically, accepting them is a bit riskier for obvious reasons, but it's a problem that's absolutely solveable.
-
Standard library is definitely useful and would make the system easier, but only in a sense that it provides some ready-to-use code for your contracts somewhere. And this can be easily handled by a public GitHub repo like
https://github.com/screeps/contract-templates
, with a link advertising this repo in the Contracts creation UI.But automatic usage of contract templates is very unlikely. Both parties should be on the same page here, using the same conventions, agreeing on the same conditions, being neighbors in the game world, having very specific needs and demands matching each other. The chance of this happening in the real world is almost zero. Too much work for such exotic feature.
-
the other party would never accept a contract with such code
We'll see.
-
In order to create some "marketplace-like" behavior to popularize contracts usage, we can develop a public offer system, where you create an offer without a direct respondent, and all interested parties can view all such public offers via special UI. When someone accepts a public offer, you're notified (both via UI and API) and should finish the deal to start the contract (again, either via UI or API).
Thus, creation and acceptance would be manual, but dealing could be both manual and automatic.
To make it more clear:
- You write code, create a contract (manually).
- You set up this contract to be public rather than directly invited (manually).
- The contract is then listed in the Public Contracts UI.
- An interested party views your contract and accepts it (manually).
- You finish the deal (either manually or automatically).
- The contract starts, you track the progress (either manually or automatically).
-
My opinion is, that very few people will use it, if it needs that much "manual " work, so its wasted develop time. First it seems to be interesting, but ghe game is about making things automatically. This way its to much manual work to look at/find contracts. As runner of a "third" party script you need to review it veeery carefully, so finding a contract needs tons of time, first you need to consider if its worth it (how much credits for the effort?) and then you need to review all possbile contracts, which one is most cpu efficient and give enough credits, which can i fullfill with least effort etc. If some people are willing to take so much time for this, they can do similiar now just by chatting /messaging people near their aim ( spawn build maybe) and ask for help/give them a code snippet /transfer some ressources/ sell /buy with terminal.
-
@artch said in Discussion: Contract system:
But automatic usage of contract templates is very unlikely. Both parties should be on the same page here, using the same conventions, agreeing on the same conditions, being neighbors in the game world, having very specific needs and demands matching each other. The chance of this happening in the real world is almost zero. Too much work for such exotic feature.
I can see your point of view. I wonder if you know what percentage of players automatically trade on the market? Probably a hard-to-gather stat, but I imagine the number of people automatically doing contracts would be quite a bit lower, so if you wrote some clever auto-contract code, the chances of anybody else nearby having code that could understand that would be rather slim.
On the other hand, what is the overhead of allowing automatic behaviour? I guess the traffic for a "getAllContracts" call would be quite high if it included the code string, so I guess it would probably have to just contain description/player/tick info. An one-tick-delayed call (like segments) that pulled a contract text string should work though, and I would have thought that'd be the only non-trivial thing to implement. Everything else, like checking the code against a third party template could be handled by the user. I do see drawnbacks in a system that only really works if you're also using a third party library, as I doubt many people would be able to do anything more complicated than a simple comparison but it seems like adding automation isn't a huge step having done all the work for non-automated contracts.
-
This feature sounds quite interesting, the first (and most interesting imo) use I thought of for this, is for private servers with bots that would offer contracts when they come into contact with the player, as a 'quest'. Upon fulfilment the bot could then offer more contracts. Effectively creating a 'quest line'.
This would obviously require some degree of automation in creation/offering of contracts (though not in acceptance of contracts), and ideally the ability to add some text with the contract for the quest descriptions. (Note: I'm mostly think of individual, i.e. effectively single player, servers. But the concept could easily scale up for multiplayer private servers).
In terms of the contracts themselves, I see them most useful if the code simply checks the criteria for completing the contract. e.g. I might offer someone a contract that simply checks that a room has no owned structures in it, other than a controller. This is obviously a contract to destroy a room, but the contractor is free to achieve this any way they want (including bribing the current owner to respawn). But to my second point, there should be a mechanism for a contract to say "I'm done, contract completed" and award the player their credits immediately (or, more likely, next tick).
Third and final point, I was thinking of how I'd check if someone had destroyed a player with multiple rooms, one option would be require they have vision in every room I wanted taken out, but using some kind of memory would be nicer for the contractor. Would it be possible to have some kind of memory that was only modifiable by the contract code for the duration of the contract (perhaps, have an option to reserve a memory segment for a contract)?
Just my thoughts.
-
From discussions in slack I came to the conclusion that contracts are most useful to check for conditions instead of executing code that queues intents.
This way contracts require an implementation from the person fulfilling the contract, which not only allows the contractor to solve it in their own way and optimize it for stuff like CPU, they can be seen as some kind of quest or mission.
I completely understand the need for manual review, but even though I'm repeating myself, limiting it to manual interaction only is a mistake in my opinion.
When going for parameterized contracts you could easily create a checksum of the module and require to review the module at least once, after that your code is free to accept any contracts with the same checksum. Additionally your code can verify whether it actually wants to accept a contract based on those parameters.
In the long term it would be nice being able to accept a contract without manual review, either by a well established list of tested contracts or by adding the exact same contract module to your own code.
Example contract
Following is a scenario of how I expect the process to look like when working with contracts.
Player A: contractee Player B: contractor
- The contractee create a contract module, in this case it's a module that requires a nuke to be sent by the contractor to a specific position:
const { x, y, roomName } = Game.contract.parameters; const pos = new RoomPosition(x, y, room); const hasVision = roomName => roomName in Game.rooms; const isMyRoom = roomName => _.get(Game.rooms, [roomName, 'controller', 'my'], false); module.exports.loop = function() { if (!hasVision(roomName)) { return false; } const nukes = pos.lookFor(LOOK_NUKE); if (!nukes) { return false; } return nukes.some(({ launchRoomName }) => isMyRoom(launchRoomName)); }
- The contractee creates a contract based on this module:
function requestNuke(pos, reward) { const { x, y, roomName } = pos; return Game.contracts.create('contract-nuke.js', reward, { x, y, roomName }); } requestNuke(new RoomPosition(25, 25, 'N0E0'), 100000);
-
The potential contractor ( Player B ) views all of the available contracts in the UI, reviews the contract's code and approves it, the checksum is then added to their list of allowed contracts.
-
Player B's code views a list of available contracts and chooses appropriately, afterwards every accepted contract is getting executed (contracts won't be accepted until the next tick). If the contract hasn't been reviewed yet an appropriate error code will get returned.
const CHECKSUM = '1b1774169003e863931fa3c5ddbfa7f1'; const MINIMUM_REWARD = 80000; const myRoom = room => _.get(room, ['controller', 'my'], false); const getNuker = room => room.find(FIND_STRUCTURES, { filter: { structureType: STRUCTURE_NUKER }}); const hasNuker = room => !!getNuker(room); const inNukeRange = (room, target) => Game.map.getRoomLinearDistance(room.name, target) <= NUKE_RANGE; function getFirstNukerInRange(targetRoom) { return _.first(_.values(Game.rooms), room => myRoom(room) && hasNuker(room) && inNukeRange(room, targetRoom)); } const isNukeContract = contract => contract.checksum === CHECKSUM; const isNukeContractValuable = contract => contract.reward >= MINIMUM_REWARD; const isNukeContractInRange = contract => !!getFirstNukerInRange(contract.parameters.roomName); function acceptNukeContracts(contract) { if (!isNukeContract(contract)) { return; } if (!isNukeContractValuable(contract)) { return; } if (!isNukeContractInRange(contract)) { return; } Game.contracts.accept(contract.id); } function executeNukeContracts(contract) { if (!isNukeContract(contract)) { return; } const { x, y, roomName } = contract.parameters; const nuker = getFirstNukerInRange(roomName); nuker.launchNuke(new RoomPosition(x, y, roomName)); } module.exports.loop = function loop() { _.forEach(Game.contracts.available, acceptNukeContracts); _.forEach(Game.contracts.accepted, executeNukeContracts); }
This is a fairly simple implementation (but devastating none the less!) but I hope this example shows how automation would be able to handle contracts.
Contracts API Draft
The following is a little draft of how the contract API could look like, it's probably a good idea to replace the properties under
Game.contracts
with a function similar toGame.market.getAllOrders
.Contract
object
property type description id string A unique identifier, can be used to interact with a contract checksum string Checksum of the contained code, each checksum will have to be allowed manually once by reviewing the associated code contractee string The player of which the contract was created contractor optional string The player that accepted the contract, might not be set yet reward number The amount of credits that the contractee pays the contractor once the contract has been fulfilled parameters otpional object Any valid json object that can be used to modify the modules behaviour -
Game.constract
: Is only available from within a contract, contains the currently executedContract
object. -
Game.contracts.available
: Array of availableContract
objects. -
Game.contracts.accepted
: Array ofContract
objects that you accepted. -
Game.contracts.created
: Array ofContract
objects that you created but are not accepted yet. -
Game.contracts.running
: Array ofContract
objects that you created any were accepted by someone else. -
Game.contracts.create(moduleName, reward, [parameters])
: Create a new contract
parameter type description moduleName string Name of the module you want to create as a contract reward number The amount of credits that the contractee pays the contractor once the contract has been fulfilled parameters otpional object Any valid json object that can be used to modify the modules behaviour Game.contracts.accept(id)
: Accept an available contract
parameter type description id string A unique identifier of the contract you want to accept