Skip to content
This repository was archived by the owner on Sep 1, 2023. It is now read-only.

Commit 9d08cc3

Browse files
committed
update how anti sabotage works
1 parent f0da2e8 commit 9d08cc3

File tree

3 files changed

+46
-24
lines changed

3 files changed

+46
-24
lines changed

src/gameLogic/notStarted.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export function startGame(game: UnoGame<false>, automatic: boolean) {
9393
currentPlayer: players[0],
9494
lastPlayer: { id: null, duration: 0 },
9595
settings,
96+
saboteurs: {},
9697
channelID: game.channelID,
9798
guildID: game.guildID,
9899
_modified: game._modified,

src/gameLogic/playedCards.ts

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,35 @@ import { cardEmotes, cards, colors, SelectIDs, uniqueVariants, variants } from "
66
import { config } from "../index.js";
77
import timeouts from "../timeouts.js";
88
import { Card, UnoGame } from "../types.js";
9-
import { getUsername, next, PickCardSelect, toTitleCase, wasLastTurnBlocked } from "../utils.js";
9+
import { getUsername, next, PickCardSelect, toTitleCase, updateStats, wasLastTurnBlocked } from "../utils.js";
1010
import { games, onTimeout, sendGameMessage } from "./index.js";
1111

12+
function isSabotage(ctx: ComponentInteraction<ComponentTypes.STRING_SELECT>, game: UnoGame<true>): boolean {
13+
// first card is duration=0, second is duration=1, etc
14+
let maxDuration = 4; // so default is kick on 5th card drawn
15+
if (game.cards[next(game.players, game.players.indexOf(game.lastPlayer.id))].length <= 2) maxDuration--;
16+
if (game.saboteurs[game.lastPlayer.id]) maxDuration--;
17+
18+
if (game.lastPlayer.duration >= maxDuration) {
19+
game.players.splice(game.players.indexOf(ctx.member.id), 1);
20+
sendMessage(ctx.channel.id, `Removed **${getUsername(game.lastPlayer.id, true, ctx.guild)}** for attempting to sabotage the game`);
21+
if (game.players.length <= 1) {
22+
updateStats(game, game.players[0]);
23+
return true;
24+
}
25+
26+
game.currentPlayer = next(game.players, game.players.indexOf(game.currentPlayer));
27+
game.lastPlayer.duration = 0;
28+
return true;
29+
}
30+
31+
if (game.lastPlayer.duration === maxDuration - 1) {
32+
game.saboteurs[game.lastPlayer.id] = true;
33+
}
34+
35+
return false;
36+
}
37+
1238
export function onColorPlayed(ctx: ComponentInteraction<ComponentTypes.STRING_SELECT>, game: UnoGame<true>) {
1339
const { currentPlayer } = game;
1440
if (currentPlayer !== ctx.member.id) return;
@@ -117,32 +143,25 @@ export function onCardPlayed(ctx: ComponentInteraction<ComponentTypes.STRING_SEL
117143

118144
let extraInfo = "";
119145
if (cardPlayed === "draw") {
120-
if (game.lastPlayer.duration >= 4 && game.settings.antiSabotage) {
121-
game.players.splice(game.players.indexOf(ctx.member.id), 1);
122-
sendMessage(ctx.channel.id, `Removed **${getUsername(game.lastPlayer.id, true, ctx.guild)}** for attempting to sabotage the game`);
123-
if (game.players.length <= 1) return;
124-
game.currentPlayer = next(game.players, game.players.indexOf(game.currentPlayer));
125-
game.lastPlayer.duration = 0;
146+
if (isSabotage(ctx, game)) return;
126147

127-
return sendGameMessage(game);
128-
} else {
129-
const { cards: newCards, newDeck } = game.draw(1);
130-
game.cards[ctx.member.id].push(newCards[0]);
131-
game.cards[ctx.member.id].sort((a, b) => cards.indexOf(a) - cards.indexOf(b));
132-
game.deck = newDeck;
133-
if (game.settings.allowSkipping) {
134-
const components = PickCardSelect(game, ctx.member.id);
135-
if (components) ctx.editOriginal({
136-
content: config.emoteless
137-
? `You drew a ${cardEmotes[newCards[0]]} ${toTitleCase(newCards[0])}`
138-
: `${game.cards[ctx.member.id].map(c => cardEmotes[c]).join(" ")}
148+
const { cards: newCards, newDeck } = game.draw(1);
149+
game.cards[ctx.member.id].push(newCards[0]);
150+
game.cards[ctx.member.id].sort((a, b) => cards.indexOf(a) - cards.indexOf(b));
151+
game.deck = newDeck;
152+
153+
if (game.settings.allowSkipping) {
154+
const components = PickCardSelect(game, ctx.member.id);
155+
if (components) ctx.editOriginal({
156+
content: config.emoteless
157+
? `You drew a ${cardEmotes[newCards[0]]} ${toTitleCase(newCards[0])}`
158+
: `${game.cards[ctx.member.id].map(c => cardEmotes[c]).join(" ")}
139159
You drew ${cardEmotes[newCards[0]]}`,
140-
components
141-
});
142-
}
143-
else
144-
ctx.deleteOriginal();
160+
components
161+
});
145162
}
163+
else
164+
ctx.deleteOriginal();
146165
}
147166

148167
else if (cardPlayed === "skip") {
@@ -154,6 +173,7 @@ You drew ${cardEmotes[newCards[0]]}`,
154173
game.currentCard = cardPlayed;
155174
game.currentCardColor = color as typeof colors[number];
156175
game.cards[ctx.member.id].splice(game.cards[ctx.member.id].indexOf(cardPlayed), 1);
176+
delete game.saboteurs[game.lastPlayer.id];
157177

158178
if (variant === "reverse") {
159179
game.players = game.players.reverse();

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export type UnoGame<T extends boolean> = T extends true ? {
6666
duration: number,
6767
},
6868
settings: UnoGameSettings,
69+
saboteurs: { [id: string]: boolean },
6970
message: Message<AnyGuildTextChannel>,
7071
channelID: string,
7172
guildID: string,

0 commit comments

Comments
 (0)