diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts
index f04b7032e..4a709fc24 100644
--- a/src/client/graphics/layers/PlayerInfoOverlay.ts
+++ b/src/client/graphics/layers/PlayerInfoOverlay.ts
@@ -1,7 +1,7 @@
import { LitElement, html, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { Layer } from './Layer';
-import { Game, GameType, Player, PlayerType, Unit, UnitType } from '../../../core/game/Game';
+import { Game, GameType, Player, PlayerType, Relation, Unit, UnitType } from '../../../core/game/Game';
import { ClientID } from '../../../core/Schemas';
import { EventBus } from '../../../core/EventBus';
import { TransformHandler } from '../TransformHandler';
@@ -114,8 +114,28 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
const isAlly = (myPlayer?.isAlliedWith(player) || player == this.myPlayer()) ?? false;
let relation = null
if (player.type() == PlayerType.FakeHuman && myPlayer != null) {
- // Don't create an HTML string, let Lit handle the templating
- relation = html`
Attitude: ${player.relation(myPlayer)}
`;
+ let classType = ''
+ let relationName = ''
+ switch (player.relation(myPlayer)) {
+ case Relation.Hostile:
+ classType = 'hostile'
+ relationName = 'Hostile'
+ break
+ case Relation.Distrustful:
+ classType = 'distrustful'
+ relationName = 'Distrustful'
+ break
+ case Relation.Neutral:
+ classType = 'neutral'
+ relationName = 'Neutral'
+ break
+ case Relation.Friendly:
+ classType = 'friendly'
+ relationName = 'Friendly'
+ break
+ }
+
+ relation = html`Attitude: ${relationName}
`;
}
return html`
@@ -273,6 +293,19 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
.type-label {
font-size: 12px;
}
+
+ }
+ .hostile {
+ color: #ff4444;
+ }
+ .distrustful {
+ color: #ff8888;
+ }
+ .neutral {
+ color: #ffffff;
+ }
+ .friendly {
+ color: #4CAF50;
}
`;
}
\ No newline at end of file
diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts
index 033d45ab7..e9d6208ae 100644
--- a/src/core/execution/AttackExecution.ts
+++ b/src/core/execution/AttackExecution.ts
@@ -101,7 +101,7 @@ export class AttackExecution implements Execution {
// No updates should happen in init.
this.breakAlliance = true
}
- this.target.updateRelation(this._owner, -500)
+ this.target.updateRelation(this._owner, -80)
}
}
diff --git a/src/core/execution/DonateExecution.ts b/src/core/execution/DonateExecution.ts
index c737f1bca..5c93b41f2 100644
--- a/src/core/execution/DonateExecution.ts
+++ b/src/core/execution/DonateExecution.ts
@@ -1,5 +1,5 @@
import { consolex } from "../Consolex";
-import {AllPlayers, Execution, MutableGame, MutablePlayer, PlayerID} from "../game/Game";
+import { Execution, MutableGame, MutablePlayer, PlayerID } from "../game/Game";
export class DonateExecution implements Execution {
@@ -26,6 +26,7 @@ export class DonateExecution implements Execution {
tick(ticks: number): void {
if (this.sender.canDonate(this.recipient)) {
this.sender.donate(this.recipient, this.troops)
+ this.recipient.updateRelation(this.sender, 50)
} else {
consolex.warn(`cannot send tropps from ${this.sender} to ${this.recipient}`)
}
diff --git a/src/core/execution/EmojiExecution.ts b/src/core/execution/EmojiExecution.ts
index e5dbcb782..04d753ab6 100644
--- a/src/core/execution/EmojiExecution.ts
+++ b/src/core/execution/EmojiExecution.ts
@@ -24,7 +24,7 @@ export class EmojiExecution implements Execution {
if (this.requestor.canSendEmoji(this.recipient)) {
this.requestor.sendEmoji(this.recipient, this.emoji)
if (this.emoji == "🖕" && this.recipient != AllPlayers && this.recipient.type() == PlayerType.FakeHuman) {
- this.recipient.updateRelation(this.requestor, -10000)
+ this.recipient.updateRelation(this.requestor, -100)
}
} else {
consolex.warn(`cannot send emoji from ${this.requestor} to ${this.recipient}`)
diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts
index edaaad30d..b8eae57bd 100644
--- a/src/core/execution/FakeHumanExecution.ts
+++ b/src/core/execution/FakeHumanExecution.ts
@@ -1,4 +1,4 @@
-import { AllianceRequest, Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tile, UnitType } from "../game/Game"
+import { AllianceRequest, Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, PlayerType, Relation, TerrainType, TerraNullius, Tile, UnitType } from "../game/Game"
import { PseudoRandom } from "../PseudoRandom"
import { and, bfs, calculateBoundingBox, dist, euclDist, manhattanDist, simpleHash } from "../Util";
import { AttackExecution } from "./AttackExecution";
@@ -144,12 +144,12 @@ export class FakeHumanExecution implements Execution {
}
const target = this.player.allies()
- .filter(ally => this.player.relation(ally) > 0)
+ .filter(ally => this.player.relation(ally) >= Relation.Neutral)
.filter(ally => ally.targets().length > 0)
.map(ally => ({ ally: ally, t: ally.targets() }))[0] ?? null
if (target != null) {
- this.player.updateRelation(target.ally, -2000)
+ this.player.updateRelation(target.ally, -20)
this.enemy = target.t[0]
this.lastEnemyUpdateTick = this.mg.ticks()
this.mg.addExecution(new EmojiExecution(this.player.id(), target.ally.id(), "👍"))
@@ -157,7 +157,7 @@ export class FakeHumanExecution implements Execution {
if (this.enemy == null) {
const mostHated = this.player.allRelationsSorted()[0] ?? null
- if (mostHated != null && mostHated.relation < - 2000) {
+ if (mostHated != null && mostHated.relation == Relation.Hostile) {
this.enemy = mostHated.player
this.lastEnemyUpdateTick = this.mg.ticks()
this.mg.addExecution(
@@ -323,7 +323,7 @@ export class FakeHumanExecution implements Execution {
this.replyToAllianceRequest(req, false)
continue
}
- if (this.player.relation(req.requestor()) < 0) {
+ if (this.player.relation(req.requestor()) < Relation.Neutral) {
this.replyToAllianceRequest(req, false)
continue
}
diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts
index c3fbafe09..d007c0c97 100644
--- a/src/core/execution/NukeExecution.ts
+++ b/src/core/execution/NukeExecution.ts
@@ -103,7 +103,7 @@ export class NukeExecution implements Execution {
this.player.breakAlliance(alliance)
}
if (other != this.player) {
- other.updateRelation(this.player, -5000)
+ other.updateRelation(this.player, -100)
}
}
}
diff --git a/src/core/execution/TargetPlayerExecution.ts b/src/core/execution/TargetPlayerExecution.ts
index 66a8735a0..b88c47e09 100644
--- a/src/core/execution/TargetPlayerExecution.ts
+++ b/src/core/execution/TargetPlayerExecution.ts
@@ -18,7 +18,7 @@ export class TargetPlayerExecution implements Execution {
tick(ticks: number): void {
if (this.requestor.canTarget(this.target)) {
this.requestor.target(this.target)
- this.target.updateRelation(this.requestor, -5000)
+ this.target.updateRelation(this.requestor, -40)
}
this.active = false
}
diff --git a/src/core/execution/alliance/AllianceRequestReplyExecution.ts b/src/core/execution/alliance/AllianceRequestReplyExecution.ts
index fd24fbd3d..7e52d6b7c 100644
--- a/src/core/execution/alliance/AllianceRequestReplyExecution.ts
+++ b/src/core/execution/alliance/AllianceRequestReplyExecution.ts
@@ -25,8 +25,8 @@ export class AllianceRequestReplyExecution implements Execution {
} else {
if (this.accept) {
request.accept()
- this.requestor.updateRelation(this.recipient, 5000)
- this.recipient.updateRelation(this.requestor, 5000)
+ this.requestor.updateRelation(this.recipient, 100)
+ this.recipient.updateRelation(this.requestor, 100)
} else {
request.reject()
}
diff --git a/src/core/execution/alliance/BreakAllianceExecution.ts b/src/core/execution/alliance/BreakAllianceExecution.ts
index a8529bfce..9ed2c552a 100644
--- a/src/core/execution/alliance/BreakAllianceExecution.ts
+++ b/src/core/execution/alliance/BreakAllianceExecution.ts
@@ -5,12 +5,14 @@ export class BreakAllianceExecution implements Execution {
private active = true
private requestor: MutablePlayer;
private recipient: MutablePlayer
+ private mg: MutableGame
constructor(private requestorID: PlayerID, private recipientID: PlayerID) { }
init(mg: MutableGame, ticks: number): void {
this.requestor = mg.player(this.requestorID)
this.recipient = mg.player(this.recipientID)
+ this.mg = mg
}
tick(ticks: number): void {
@@ -19,7 +21,12 @@ export class BreakAllianceExecution implements Execution {
consolex.warn('cant break alliance, not allied')
} else {
this.requestor.breakAlliance(alliance)
- this.recipient.updateRelation(this.requestor, -5000)
+ this.recipient.updateRelation(this.requestor, -200)
+ for (const player of this.mg.players()) {
+ if (player != this.requestor) {
+ player.updateRelation(this.requestor, -40)
+ }
+ }
}
this.active = false
}
diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts
index 05cd08a08..b62db108b 100644
--- a/src/core/game/Game.ts
+++ b/src/core/game/Game.ts
@@ -53,6 +53,13 @@ export enum UnitType {
City = "City"
}
+export enum Relation {
+ Hostile = 0,
+ Distrustful = 1,
+ Neutral = 2,
+ Friendly = 3
+}
+
export class Nation {
constructor(
public readonly name: string,
@@ -242,9 +249,9 @@ export interface Player {
// TODO: why can't I have "canSendAllyRequest" function instead?
recentOrPendingAllianceRequestWith(other: Player): boolean
// How this player feels about other player.
- relation(other: Player): number
+ relation(other: Player): Relation
// Sorted from most hated to most liked
- allRelationsSorted(): { player: Player, relation: number }[]
+ allRelationsSorted(): { player: Player, relation: Relation }[]
isTraitor(): boolean
canTarget(other: Player): boolean
// Targets for this player
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index fab9a6987..f344aa9a9 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -1,4 +1,4 @@
-import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit } from "./Game";
+import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit, Relation } from "./Game";
import { ClientID } from "../Schemas";
import { assertNever, bfs, closestOceanShoreFromPlayer, dist, distSortUnit, manhattanDist, manhattanDistWrapped, processName, simpleHash, sourceDstOceanShore, within } from "../Util";
import { CellString, GameImpl } from "./GameImpl";
@@ -200,19 +200,33 @@ export class PlayerImpl implements MutablePlayer {
return this.gs.createAllianceRequest(this, recipient as MutablePlayer)
}
- relation(other: Player): number {
+ relation(other: Player): Relation {
if (other == this) {
throw new Error(`cannot get relation with self: ${this}`)
}
if (this.relations.has(other)) {
- return this.relations.get(other)
+ return this.relationFromValue(this.relations.get(other))
}
- return 0
+ return Relation.Neutral
}
- allRelationsSorted(): { player: Player, relation: number }[] {
+ private relationFromValue(relationValue: number): Relation {
+ if (relationValue < -50) {
+ return Relation.Hostile
+ }
+ if (relationValue < 0) {
+ return Relation.Distrustful
+ }
+ if (relationValue < 50) {
+ return Relation.Neutral
+ }
+ return Relation.Friendly
+ }
+
+ allRelationsSorted(): { player: Player, relation: Relation }[] {
return Array.from(this.relations, ([k, v]) => ({ player: k, relation: v }))
.sort((a, b) => a.relation - b.relation)
+ .map(r => ({ player: r.player, relation: this.relationFromValue(r.relation) }))
}
updateRelation(other: Player, delta: number): void {
@@ -223,18 +237,16 @@ export class PlayerImpl implements MutablePlayer {
if (this.relations.has(other)) {
relation = this.relations.get(other)
}
- const newRelation = within(relation + delta, -10000, 10000)
+ const newRelation = within(relation + delta, -100, 100)
this.relations.set(other, newRelation)
}
decayRelations() {
this.relations.forEach((r: number, p: Player) => {
- // Have relationships decay over time
- if (r > 1) {
- r -= 1
- } else if (r < -1) {
- r += 1
- } else {
+ const sign = -1 * Math.sign(r)
+ const delta = .05
+ r += sign * delta
+ if (Math.abs(r) < delta * 2) {
r = 0
}
this.relations.set(p, r)