aaaaaaaaaaaaaaaaaa

This commit is contained in:
jude
2023-04-30 18:42:52 +01:00
parent 0fed48b79d
commit 9c6b251a25
12 changed files with 294 additions and 88 deletions

View File

@ -12,6 +12,7 @@ export class Game {
this.us = null;
this.players = {};
this.state = WAITING;
this.contendedRegion = null;
this.allPlaced = false;
}

View File

@ -165,6 +165,11 @@ document.addEventListener("ACT", async (ev) => {
}
});
document.addEventListener("RESOLVE", (ev) => {
const data = ev.detail;
game.contendedRegion.handleResolve(data);
});
// todo has to filter by player
document.addEventListener("PROOF", async (ev) => {
const data = ev.detail;

View File

@ -113,6 +113,10 @@ export class Region {
this.neighbours = new Set();
this.continent = continent;
this.attackResolver = null;
this.attackerRes = null;
this.defenderRes = null;
REGIONS[name] = this;
}
@ -172,6 +176,48 @@ export class Region {
verify(plainText, a) {
this.strength.verify(this.name, plainText, a);
}
async handleResolve(resolution) {
await navigator.locks.request(`region-${this.name}`, () => {
if (resolution.author === this.owner.id) {
this.defenderRes = resolution;
} else {
this.attackerRes = resolution;
}
if (
this.attackResolver !== null &&
this.defenderRes !== null &&
this.attackerRes !== null
) {
this.attackResolver({
attackerRes: this.attackerRes,
defenderRes: this.defenderRes,
});
}
});
}
async resolveAttack() {
let promise;
await navigator.locks.request(`region-${this.name}`, () => {
if (this.attackerRes === null || this.defenderRes === null) {
let resolver;
promise = new Promise((resolve) => {
resolver = resolve;
});
this.attackResolver = resolver;
} else {
promise = new Promise((resolve) => {
resolve({
attackerRes: this.attackerRes,
defenderRes: this.defenderRes,
});
});
}
});
return promise;
}
}
window.Region = Region;

View File

@ -161,4 +161,28 @@ export class Packet {
region: region,
});
}
static createRegionProof(proof) {
return this._sign({
...this._createBase("RESOLVE"),
action: "MAINTAIN",
proof: proof,
});
}
static createRegionYield() {
return this._sign({
...this._createBase("RESOLVE"),
action: "YIELD",
proof: proof,
});
}
static createRegionCapture(cipherText) {
return this._sign({
...this._createBase("RESOLVE"),
action: "CAPTURE",
cipherText: cipherText,
});
}
}

View File

@ -5,6 +5,7 @@ import { PaillierPubKey, ReadOnlyCiphertext } from "../crypto/paillier.js";
import { Region } from "./map.js";
import { showDefenseDom } from "./dom.js";
import {
proveBitLength,
proveFortify,
proveRange,
proveRegions,
@ -325,6 +326,8 @@ export class Player {
return false;
}
game.contendedRegion = defender;
// If we're the defender, we need to send a packet to state our defense.
if (defender.owner === game.us) {
showDefenseDom(defender.name);
@ -340,8 +343,6 @@ export class Player {
defenderStrength = await defender.owner.getDefense();
}
console.log(defenderStrength);
/* How do Risk attacks work?
- Offender signs 1-3 armies, defender signs 1-2 armies
- Both roll respective dice
@ -387,10 +388,16 @@ export class Player {
// Handle aftermath.
if (defender.owner === game.us) {
if (defender.strength.cipherText.plainText === 0n) {
// Handle region loss
// State we don't control the region. This makes programming easier.
socket.emit("message", Packet.createRegionYield());
} else {
let ct = defender.strength.cipherText.clone();
ct.update(new Ciphertext(ct.pubKey, -2n, 0n));
// Prove we still control the region
let proof = proveRange(defender.strength.cipherText, 2n ** 32n);
let proof = proveBitLength(ct);
// Send proof we maintain it
socket.emit("message", Packet.createRegionProof(proof));
}
} else if (this === game.us) {
if (defender.strength.assumedStrength === 0n) {
@ -400,14 +407,29 @@ export class Player {
new Ciphertext(this.paillierPubKey, offenderRolls.length + 1),
defender.name
);
// Send the new ciphertext
socket.emit(
"message",
Packet.createRegionCapture(defender.strength.cipherText)
);
} else {
// State we didn't capture. Again, makes programming easier.
socket.emit("message", Packet.createRegionYield());
}
} else {
await defender.resolveConflict();
let resolutions = await defender.resolveAttack();
console.log(resolutions);
}
// Reset the promises in case they attack again.
defender.owner.defenderPromise = null;
defender.owner.defenderAmount = null;
defender.defenderRes = null;
defender.attackerRes = null;
defender.attackResolver = null;
game.contendedRegion = null;
}
async setDefense(amount) {

View File

@ -1,7 +1,7 @@
import { cryptoRandom } from "../crypto/random_primes.js";
import { Region } from "./map.js";
const ROUNDS = 24;
const ROUNDS = 12;
function cryptoRange(upper) {
// This is ridiculous: why implement a BigInt primitive, have it behave like a number, and then _not_ offer