diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 013b5d298..a9ee93fe9 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -88,7 +88,7 @@ export class SendTargetPlayerIntentEvent implements GameEvent { export class SendEmojiIntentEvent implements GameEvent { constructor( public readonly recipient: PlayerView | typeof AllPlayers, - public readonly emoji: string, + public readonly emoji: number, ) {} } diff --git a/src/client/graphics/layers/EmojiTable.ts b/src/client/graphics/layers/EmojiTable.ts index 5db92c866..b8a9e4bd6 100644 --- a/src/client/graphics/layers/EmojiTable.ts +++ b/src/client/graphics/layers/EmojiTable.ts @@ -4,24 +4,11 @@ import { EventBus } from "../../../core/EventBus"; import { AllPlayers } from "../../../core/game/Game"; import { GameView, PlayerView } from "../../../core/game/GameView"; import { TerraNulliusImpl } from "../../../core/game/TerraNulliusImpl"; +import { emojiTable, flattenedEmojiTable } from "../../../core/Util"; import { ShowEmojiMenuEvent } from "../../InputHandler"; import { SendEmojiIntentEvent } from "../../Transport"; import { TransformHandler } from "../TransformHandler"; -const emojiTable: string[][] = [ - ["😀", "😊", "🥰", "😇", "😎"], - ["😞", "🥺", "😭", "😱", "😡"], - ["😈", "🤡", "🖕", "🥱", "🤦‍♂️"], - ["👋", "👏", "🤌", "💪", "🫡"], - ["👍", "👎", "❓", "🐔", "🐀"], - ["🤝", "🆘", "🕊️", "🏳️", "⏳"], - ["🔥", "💥", "💀", "☢️", "⚠️"], - ["↖️", "⬆️", "↗️", "👑", "🥇"], - ["⬅️", "🎯", "➡️", "🥈", "🥉"], - ["↙️", "⬇️", "↘️", "❤️", "💔"], - ["💰", "⚓", "⛵", "🏡", "🛡️"], -]; - @customElement("emoji-table") export class EmojiTable extends LitElement { public eventBus: EventBus; @@ -130,7 +117,12 @@ export class EmojiTable extends LitElement { targetPlayer == this.game.myPlayer() ? AllPlayers : (targetPlayer as PlayerView); - this.eventBus.emit(new SendEmojiIntentEvent(recipient, emoji)); + this.eventBus.emit( + new SendEmojiIntentEvent( + recipient, + flattenedEmojiTable.indexOf(emoji), + ), + ); this.hideTable(); }); }); diff --git a/src/client/graphics/layers/PlayerPanel.ts b/src/client/graphics/layers/PlayerPanel.ts index 5301ba2b1..371b45989 100644 --- a/src/client/graphics/layers/PlayerPanel.ts +++ b/src/client/graphics/layers/PlayerPanel.ts @@ -15,6 +15,7 @@ import { } from "../../../core/game/Game"; import { TileRef } from "../../../core/game/GameMap"; import { GameView, PlayerView } from "../../../core/game/GameView"; +import { flattenedEmojiTable } from "../../../core/Util"; import { MouseUpEvent } from "../../InputHandler"; import { SendAllianceRequestIntentEvent, @@ -122,9 +123,16 @@ export class PlayerPanel extends LitElement implements Layer { e.stopPropagation(); this.emojiTable.showTable((emoji: string) => { if (myPlayer == other) { - this.eventBus.emit(new SendEmojiIntentEvent(AllPlayers, emoji)); + this.eventBus.emit( + new SendEmojiIntentEvent( + AllPlayers, + flattenedEmojiTable.indexOf(emoji), + ), + ); } else { - this.eventBus.emit(new SendEmojiIntentEvent(other, emoji)); + this.eventBus.emit( + new SendEmojiIntentEvent(other, flattenedEmojiTable.indexOf(emoji)), + ); } this.emojiTable.hideTable(); this.hide(); diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 94fa5e369..b08fcfcfb 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -9,6 +9,7 @@ import { PlayerType, UnitType, } from "./game/Game"; +import { flattenedEmojiTable } from "./Util"; export type GameID = string; export type ClientID = string; @@ -133,14 +134,10 @@ const SafeString = z ) .max(1000); -const EmojiSchema = z.string().refine( - (val) => { - return /\p{Emoji}/u.test(val); - }, - { - message: "Must contain at least one emoji character", - }, -); +const EmojiSchema = z + .number() + .nonnegative() + .max(flattenedEmojiTable.length - 1); const ID = z .string() .regex(/^[a-zA-Z0-9]+$/) diff --git a/src/core/Util.ts b/src/core/Util.ts index 489d53bb1..3efc15240 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -307,3 +307,19 @@ export function createRandomName( } return randomName; } + +export const emojiTable: string[][] = [ + ["😀", "😊", "🥰", "😇", "😎"], + ["😞", "🥺", "😭", "😱", "😡"], + ["😈", "🤡", "🖕", "🥱", "🤦‍♂️"], + ["👋", "👏", "🤌", "💪", "🫡"], + ["👍", "👎", "❓", "🐔", "🐀"], + ["🤝", "🆘", "🕊️", "🏳️", "⏳"], + ["🔥", "💥", "💀", "☢️", "⚠️"], + ["↖️", "⬆️", "↗️", "👑", "🥇"], + ["⬅️", "🎯", "➡️", "🥈", "🥉"], + ["↙️", "⬇️", "↘️", "❤️", "💔"], + ["💰", "⚓", "⛵", "🏡", "🛡️"], +]; +// 2d to 1d array +export const flattenedEmojiTable: string[] = [].concat(...emojiTable); diff --git a/src/core/execution/EmojiExecution.ts b/src/core/execution/EmojiExecution.ts index fb6513c74..fd816058e 100644 --- a/src/core/execution/EmojiExecution.ts +++ b/src/core/execution/EmojiExecution.ts @@ -7,6 +7,7 @@ import { PlayerID, PlayerType, } from "../game/Game"; +import { flattenedEmojiTable } from "../Util"; export class EmojiExecution implements Execution { private requestor: Player; @@ -17,7 +18,7 @@ export class EmojiExecution implements Execution { constructor( private senderID: PlayerID, private recipientID: PlayerID | typeof AllPlayers, - private emoji: string, + private emoji: number, ) {} init(mg: Game, ticks: number): void { @@ -38,10 +39,12 @@ export class EmojiExecution implements Execution { } tick(ticks: number): void { + const emojiString = flattenedEmojiTable.at(this.emoji); + if (this.requestor.canSendEmoji(this.recipient)) { - this.requestor.sendEmoji(this.recipient, this.emoji); + this.requestor.sendEmoji(this.recipient, emojiString); if ( - this.emoji == "🖕" && + emojiString == "🖕" && this.recipient != AllPlayers && this.recipient.type() == PlayerType.FakeHuman ) { diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index c7e6953f0..9870fe662 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -17,7 +17,7 @@ import { import { euclDistFN, manhattanDistFN, TileRef } from "../game/GameMap"; import { PseudoRandom } from "../PseudoRandom"; import { GameID } from "../Schemas"; -import { calculateBoundingBox, simpleHash } from "../Util"; +import { calculateBoundingBox, flattenedEmojiTable, simpleHash } from "../Util"; import { ConstructionExecution } from "./ConstructionExecution"; import { EmojiExecution } from "./EmojiExecution"; import { NukeExecution } from "./NukeExecution"; @@ -43,6 +43,7 @@ export class FakeHumanExecution implements Execution { private lastEmojiSent = new Map(); private lastNukeSent: [Tick, TileRef][] = []; private embargoMalusApplied = new Set(); + private heckleEmoji: number[]; constructor( gameID: GameID, @@ -55,6 +56,7 @@ export class FakeHumanExecution implements Execution { this.attackTick = this.random.nextInt(0, this.attackRate); this.triggerRatio = this.random.nextInt(60, 90) / 100; this.reserveRatio = this.random.nextInt(30, 60) / 100; + this.heckleEmoji = ["🤡", "😡"].map((e) => flattenedEmojiTable.indexOf(e)); } init(mg: Game) { @@ -267,7 +269,7 @@ export class FakeHumanExecution implements Execution { new EmojiExecution( this.player.id(), enemy.id(), - this.random.randElement(["🤡", "😡"]), + this.random.randElement(this.heckleEmoji), ), ); } diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index 0851e78bb..4f1d5fde9 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -8,6 +8,7 @@ import { Tick, } from "../../game/Game"; import { PseudoRandom } from "../../PseudoRandom"; +import { flattenedEmojiTable } from "../../Util"; import { AttackExecution } from "../AttackExecution"; import { EmojiExecution } from "../EmojiExecution"; @@ -15,13 +16,17 @@ export class BotBehavior { private enemy: Player | null = null; private enemyUpdated: Tick; + private assistAcceptEmoji: number; + constructor( private random: PseudoRandom, private game: Game, private player: Player, private triggerRatio: number, private reserveRatio: number, - ) {} + ) { + this.assistAcceptEmoji = flattenedEmojiTable.indexOf("👍"); + } handleAllianceRequests() { for (const req of this.player.incomingAllianceRequests()) { @@ -33,7 +38,7 @@ export class BotBehavior { } } - private emoji(player: Player, emoji: string) { + private emoji(player: Player, emoji: number) { if (player.type() !== PlayerType.Human) return; this.game.addExecution( new EmojiExecution(this.player.id(), player.id(), emoji), @@ -78,7 +83,7 @@ export class BotBehavior { this.player.updateRelation(ally, -20); this.enemy = target; this.enemyUpdated = this.game.ticks(); - this.emoji(ally, "👍"); + this.emoji(ally, this.assistAcceptEmoji); break outer; } }