Discussion: Contract system


  • Dev Team

    @postcrafter

    Taking your example from above, if someone wants to setup two contracts for different sourceIds, 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:

    @postcrafter

    Taking your example from above, if someone wants to setup two contracts for different sourceIds, 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.


  • Dev Team

    @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.


  • Culture

    @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).


  • Culture

    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.


  • Dev Team

    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.


  • CoPS

    the other party would never accept a contract with such code

    We'll see.


  • Dev Team

    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:

    1. You write code, create a contract (manually).
    2. You set up this contract to be public rather than directly invited (manually).
    3. The contract is then listed in the Public Contracts UI.
    4. An interested party views your contract and accepts it (manually).
    5. You finish the deal (either manually or automatically).
    6. 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

    1. 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));
    }
    
    
    1. 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);
    
    1. 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.

    2. 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 to Game.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 executed Contract object.

    • Game.contracts.available: Array of available Contract objects.

    • Game.contracts.accepted: Array of Contract objects that you accepted.

    • Game.contracts.created: Array of Contract objects that you created but are not accepted yet.

    • Game.contracts.running: Array of Contract 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
    πŸ‘


  • @artch

    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)

    Glad to hear. Is there any plan to support "catalog" contracts? (i.e. the contractor creates a "catalog entry" for remote mine defense), and players are free to accept that offer with certain terms (e.g. {room: "W12N14", whitelist:["Alice","Bob","James"]}), and the contract module contains a function to calculate the cost for different parameter sets.

    Little example pseudocode I wrote for a module:

    //@param options.room: string (Room name of room to be defended)
    //@param options.whitelist: string[] (People to not shoot at)
    
    module.exports.loop = function(options) {
    	if no creep exists
    		spawn creep
    		return false
    	if creep.room != options.room
    		moveTo room
    		return false
    	else
    		hostiles=find creeps not in options.whitelist
    		if (hostiles.length>0)
    			attack(hostiles[0])
    		return true
    }
    
    module.exports.bid = function(options) {
    	myroom=find my closest room to options.room
    	range=distance between myroom and options.room
    	if (range>10) {
    		return false; //No-bid on this one.
    	} else {
    		//bid 100*range credits as a contractor's fee.
    		return 100*range;
    	}
    }
    

    Without at least automating simple contracts like this with variable parameters, I can't see contracts becoming very useful. (This lowers the barrier to entry so that even small 1000-tick-long contracts could be practical. If 2 people need to be online at the same time and negotiating, working with contracts would be a massive effort and inconvenience.)

    While I understand that automated code-review is not something that you would be interested in allowing, if a module like that could be setup as a non-editable offer in a player's "catalog", then other players could manually review the code, and have their code automatically request quotes/bids for tasks.

    I don't see contracts being very useful if you have to negotiate them every time. Imagine if you had to negotiate the price of food with the manager every time you went to the store! Trade would be impossible.

    It is handled as usual, you will see an error in your console.

    But if contracts are "read-only", is there any way to fix this error? Perhaps have something like: if a contract fails an assert(), then it dies at no cost to either player?



  • I have to agree with some others. I can see that it is interesting concept. But I think it will see little uptake for the amount of development effort, I could well be wrong. But it seems to me other areas should have a higher priority.

    Wasn’t there a battle arena planned? πŸ™‚

    Battleground type matches between geographically distant players would be awesome and allow low level GCL players to get experience with battle in a safe β€˜non-ganky’ way and give high level players the ability to show off their prowess as they wish to.

    Anyway. Veering widely off-topic.

    βž•


  • @artch said in Discussion: Contract system:

    @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.

    That's what worry me the most. Looking at a code snippet doesn't account for prototypes and global changes.

    Example with the code given in first message: what if I change creep.prototype.harvest() to always return OK ? Or what if I change _.find() to return a custom object (with similar methods to Creep) ?

    If I cannot ensure that the code is reliable, it's very dangerous.

    Regards, Hiryus



  • @kraiik said in Discussion: Contract system:

    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'.

    Thats the most interesting think i read in today. I for myself wish more casual npc elements, like events of spawning raiders (a little bit more than the normal invaders, maybe a small base, like a playerroom at rc3-6), other biomes, bosses, small quests/instance shards. Maybe the contract system is a way to more active gameplay. Sharing code can be interessting, but i am not sure how usefull it could be. It can bring more player interaction, but i think a kind of ingame "clan system" would be better/easier for this.



  • Don't know if this was mentioned, but running contracts at the end of the tick might be problematic. More flexible way would be allowing contracts to be listed and executed as part of main tick (maybe as an option, default being at the end of the tick). This will allow better CPU handling (especially in the context of an OS). Contracts can then make executing frequency to be a requirement if it matters. Host can run contracts before own optional and expensive code.

    An option for exposing some clearly separated host code would be nice too. Then players can define and implement interfaces for basic things like creep spawning. We already have POSIS (a solution waiting for a problem currently :)) that is implemented by several people and can be easily implemented by anyone running an OS.

    For example contract can take in a context object provided by the host. It would be up to contact writer and host to negotiate exact details.

    let context = {};

    Game.contracts.forEach((c) => c.execute(context));



  • Quick thoughts (@o4kapuk here you go):

    1. Contract versioning so that you can run a contract you've verified before without having to check for changes.

    2. Contracts where you pay to run them so that you can rent code. Eg buying defense code from someone when you're under attack or renting room startup code for intershard portals. Also automated room planner would be great for contracts. Basically contracts could be NPM modules that you could run for a fee.

    3. Automation is a must.

    4. Barebones autoreview for contracts that checks for unclaiming/respawn/evals/infinite loops etc will be made either by the community or packaged with it

    5. Contract entrance/exit functions. Graceful ways to start and end contracts, eg if a contract stores things in memory to have it clean up after itself and make sure its not overwriting. Eg accept contract, start contract, run contract, end contract.

    6. Contract specific memory segment would make contracts cleaner to write and run.

    7. Contract permissions: allow for limiting contracts access (eg app permissions) like sandboxing memory to that segment or locking market.

    πŸ‘πŸ»


  • I think finishing what is already drafted... like power creeps.. should be a priority. Before even drafting new features.

    Just my 2 cents though.