Skip to content

Commit 6533b4d

Browse files
committed
Fixed linter issues
1 parent 443cdc1 commit 6533b4d

File tree

2 files changed

+101
-68
lines changed

2 files changed

+101
-68
lines changed

src/components/games/connectFour.ts

Lines changed: 99 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,10 @@ import { SapphireMessageResponse, SapphireSentMessageType } from '../../codeyCom
1010
import { openDB } from '../db';
1111
import { CodeyUserError } from '../../codeyUserError';
1212
import { getEmojiByName } from '../emojis';
13-
import { getRandomIntFrom1 } from '../../utils/num';
14-
import { isNull } from 'lodash';
1513

1614
const CONNECT_FOUR_COLUMN_COUNT = 7;
1715
const CONNECT_FOUR_ROW_COUNT = 6;
1816

19-
const TWO_IN_A_ROW_WEIGHT = 1;
20-
const THREE_IN_A_ROW_WEIGHT = 3;
21-
22-
2317
class ConnectFourGameTracker {
2418
// Key = id, Value = game
2519
games: Map<number, ConnectFourGame>;
@@ -251,7 +245,6 @@ export class ConnectFourGame {
251245
state: ConnectFourGameState,
252246
columnIndex: number,
253247
): Promise<ConnectFourGameStatus> {
254-
255248
// Instead of exhaustively checking every combination of tokens we can simply use the fact that
256249
// as of this point the user hasn't won yet, so we just need to check if the token that was just placed
257250
// is part of a winning combination
@@ -412,138 +405,178 @@ ${this.state.player2Username}: ${getEmojiFromSign(this.state.player2Sign)}
412405
// Player1TimeOut = 5,
413406
// Player2TimeOut = 6,
414407
// Unknown = 7,
415-
private updateState = (state : ConnectFourGameState, columnNumber : number, turn : ConnectFourGameSign): ConnectFourGameState => {
416-
const fill : number = state.columns[columnNumber].fill;
417-
if (turn === ConnectFourGameSign.Player2){
408+
private updateState = (
409+
state: ConnectFourGameState,
410+
columnNumber: number,
411+
turn: ConnectFourGameSign,
412+
): ConnectFourGameState => {
413+
const fill: number = state.columns[columnNumber].fill;
414+
if (turn === ConnectFourGameSign.Player2) {
418415
state.columns[columnNumber].tokens[fill] = ConnectFourGameSign.Player2;
419-
} else{
416+
} else {
420417
state.columns[columnNumber].tokens[fill] = ConnectFourGameSign.Player1;
421418
}
422419
state.columns[columnNumber].fill = state.columns[columnNumber].fill + 1;
423420
return state;
424-
}
421+
};
425422

426423
// returns number of possible wins remaining
427-
private possibleWins = (state : ConnectFourGameState, opponentSign : ConnectFourGameSign): number => {
428-
let possibleWins : number = 0;
424+
private possibleWins = (
425+
state: ConnectFourGameState,
426+
opponentSign: ConnectFourGameSign,
427+
): number => {
428+
let possibleWins = 0;
429429
// check vertical
430-
for (let i = 0; i < CONNECT_FOUR_COLUMN_COUNT; i++){
431-
for (let j = 3; j < CONNECT_FOUR_ROW_COUNT; j++){
432-
if (state.columns[i].tokens[j] !== opponentSign && state.columns[i].tokens[j-1] !== opponentSign && state.columns[i].tokens[j-2] !== opponentSign && state.columns[i].tokens[j-3] !== opponentSign){
430+
for (let i = 0; i < CONNECT_FOUR_COLUMN_COUNT; i++) {
431+
for (let j = 3; j < CONNECT_FOUR_ROW_COUNT; j++) {
432+
if (
433+
state.columns[i].tokens[j] !== opponentSign &&
434+
state.columns[i].tokens[j - 1] !== opponentSign &&
435+
state.columns[i].tokens[j - 2] !== opponentSign &&
436+
state.columns[i].tokens[j - 3] !== opponentSign
437+
) {
433438
possibleWins = possibleWins + 1;
434439
}
435440
}
436441
}
437442
// check horizonal
438-
for (let j = 0; j < CONNECT_FOUR_ROW_COUNT; j++){
439-
for (let i = 3; i < CONNECT_FOUR_COLUMN_COUNT; i++){
440-
if (state.columns[i].tokens[j] !== opponentSign && state.columns[i-1].tokens[j] !== opponentSign && state.columns[i-2].tokens[j] !== opponentSign && state.columns[i-3].tokens[j] !== opponentSign){
443+
for (let j = 0; j < CONNECT_FOUR_ROW_COUNT; j++) {
444+
for (let i = 3; i < CONNECT_FOUR_COLUMN_COUNT; i++) {
445+
if (
446+
state.columns[i].tokens[j] !== opponentSign &&
447+
state.columns[i - 1].tokens[j] !== opponentSign &&
448+
state.columns[i - 2].tokens[j] !== opponentSign &&
449+
state.columns[i - 3].tokens[j] !== opponentSign
450+
) {
441451
possibleWins = possibleWins + 1;
442452
}
443453
}
444454
}
445455
// check diagonal up
446-
for (let i = 0; i <= 3; i++){
447-
for (let j = 0; j <= 2; j++){
448-
if (state.columns[i].tokens[j] !== opponentSign && state.columns[i+1].tokens[j+1] !== opponentSign && state.columns[i+2].tokens[j+2] !== opponentSign && state.columns[i+3].tokens[j+3] !== opponentSign){
456+
for (let i = 0; i <= 3; i++) {
457+
for (let j = 0; j <= 2; j++) {
458+
if (
459+
state.columns[i].tokens[j] !== opponentSign &&
460+
state.columns[i + 1].tokens[j + 1] !== opponentSign &&
461+
state.columns[i + 2].tokens[j + 2] !== opponentSign &&
462+
state.columns[i + 3].tokens[j + 3] !== opponentSign
463+
) {
449464
possibleWins = possibleWins + 1;
450465
}
451466
}
452467
}
453468

454469
//check diagonal down
455-
for (let i = 3; i < CONNECT_FOUR_COLUMN_COUNT; i++){
456-
for (let j = 0; j <= 2; j++){
457-
if (state.columns[i].tokens[j] !== opponentSign && state.columns[i-1].tokens[j+1] !== opponentSign && state.columns[i-2].tokens[j+2] !== opponentSign && state.columns[i-3].tokens[j+3] !== opponentSign){
470+
for (let i = 3; i < CONNECT_FOUR_COLUMN_COUNT; i++) {
471+
for (let j = 0; j <= 2; j++) {
472+
if (
473+
state.columns[i].tokens[j] !== opponentSign &&
474+
state.columns[i - 1].tokens[j + 1] !== opponentSign &&
475+
state.columns[i - 2].tokens[j + 2] !== opponentSign &&
476+
state.columns[i - 3].tokens[j + 3] !== opponentSign
477+
) {
458478
possibleWins = possibleWins + 1;
459479
}
460480
}
461481
}
462482
return possibleWins;
463-
}
483+
};
464484

465485
// takes a ConnectFourGameState and evaluates it according to heuristic function
466-
private evaluate = (state : ConnectFourGameState): number => {
467-
let codeyPoints : number = this.possibleWins(state, ConnectFourGameSign.Player1); // 3 represents Codeybot sign
468-
let opponentPoints : number = this.possibleWins(state, ConnectFourGameSign.Player2); // 2 represents player1 sign
486+
private evaluate = (state: ConnectFourGameState): number => {
487+
const codeyPoints: number = this.possibleWins(state, ConnectFourGameSign.Player1); // 3 represents Codeybot sign
488+
const opponentPoints: number = this.possibleWins(state, ConnectFourGameSign.Player2); // 2 represents player1 sign
469489
return codeyPoints - opponentPoints;
470-
}
490+
};
471491

472-
// from perspective of Codeybot, +infinity means Codeybot win, -infinity means Player1 wins
473-
// returns the best possible score that can be achieved, given that Player1 plays optimally
474-
private miniMax = (state : ConnectFourGameState, depth : number, turn : ConnectFourGameSign): number =>{
475-
if (state.status === ConnectFourGameStatus.Draw){
492+
// from perspective of Codeybot, +infinity means Codeybot win, -infinity means Player1 wins
493+
// returns the best possible score that can be achieved, given that Player1 plays optimally
494+
private miniMax = (
495+
state: ConnectFourGameState,
496+
depth: number,
497+
turn: ConnectFourGameSign,
498+
): number => {
499+
if (state.status === ConnectFourGameStatus.Draw) {
476500
return 0;
477501
}
478-
if (state.status === ConnectFourGameStatus.Player1Win){
502+
if (state.status === ConnectFourGameStatus.Player1Win) {
479503
return -Infinity;
480504
}
481-
if (state.status === ConnectFourGameStatus.Player2Win){
505+
if (state.status === ConnectFourGameStatus.Player2Win) {
482506
return Infinity;
483507
}
484-
if (depth === 0){
508+
if (depth === 0) {
485509
return this.evaluate(state); //heuristic function to evaluate state of game
486510
}
487511

488512
// if it is Codeybot's turn, we want to find move that maximizes score
489-
const column_choices : number[] = [0, 1, 2, 3, 4, 5, 6];
490-
if (turn === ConnectFourGameSign.Player2){
491-
let value : number = -Infinity;
492-
for (const column_choice of column_choices){
493-
if (state.columns[column_choice].fill < CONNECT_FOUR_ROW_COUNT){
494-
let newState : ConnectFourGameState = JSON.parse(JSON.stringify(state));
513+
const column_choices: number[] = [0, 1, 2, 3, 4, 5, 6];
514+
if (turn === ConnectFourGameSign.Player2) {
515+
let value = -Infinity;
516+
for (const column_choice of column_choices) {
517+
if (state.columns[column_choice].fill < CONNECT_FOUR_ROW_COUNT) {
518+
const newState: ConnectFourGameState = JSON.parse(JSON.stringify(state));
495519
this.updateState(newState, column_choice, turn);
496520
this.setStatus(newState, column_choice); // setStatus assumes newState has already been updated with chip
497521
value = Math.max(value, this.miniMax(newState, depth - 1, ConnectFourGameSign.Player1));
498522
}
499523
}
500524
return value;
501-
} else { //it is Player 1's turn, so we want to find minimum score (this assumes Player 1 plays optimally)
502-
let value : number = Infinity;
503-
for (const column_choice of column_choices){
525+
} else {
526+
//it is Player 1's turn, so we want to find minimum score (this assumes Player 1 plays optimally)
527+
let value = Infinity;
528+
for (const column_choice of column_choices) {
504529
// if selected column is not already full, recurse down the branch
505-
if (state.columns[column_choice].fill < CONNECT_FOUR_ROW_COUNT){
506-
let newState : ConnectFourGameState = JSON.parse(JSON.stringify(state));
530+
if (state.columns[column_choice].fill < CONNECT_FOUR_ROW_COUNT) {
531+
const newState: ConnectFourGameState = JSON.parse(JSON.stringify(state));
507532
this.updateState(newState, column_choice, turn);
508533
this.setStatus(newState, column_choice);
509534
value = Math.min(value, this.miniMax(newState, depth - 1, ConnectFourGameSign.Player2));
510535
}
511536
}
512537
return value;
513538
}
514-
}
539+
};
515540

516-
private findBestColumn = (state : ConnectFourGameState): number =>{
517-
let column_scores : number[] = [-Infinity, -Infinity, -Infinity, -Infinity, -Infinity, -Infinity, -Infinity];
518-
for (let i = 0; i < 7; i++){
519-
if (state.columns[i].fill < CONNECT_FOUR_ROW_COUNT){
520-
let newState : ConnectFourGameState = JSON.parse(JSON.stringify(state)); // make a deep copy of game state
541+
private findBestColumn = (state: ConnectFourGameState): number => {
542+
const column_scores: number[] = [
543+
-Infinity,
544+
-Infinity,
545+
-Infinity,
546+
-Infinity,
547+
-Infinity,
548+
-Infinity,
549+
-Infinity,
550+
];
551+
for (let i = 0; i < 7; i++) {
552+
if (state.columns[i].fill < CONNECT_FOUR_ROW_COUNT) {
553+
const newState: ConnectFourGameState = JSON.parse(JSON.stringify(state)); // make a deep copy of game state
521554
this.updateState(newState, i, ConnectFourGameSign.Player2);
522555
this.setStatus(newState, i);
523556
column_scores[i] = this.miniMax(newState, 4, ConnectFourGameSign.Player1);
524-
}
557+
}
525558
}
526559
let value = -Infinity;
527560
let best_column = -1;
528-
for (let i = 0; i < 7; i++){
529-
if (column_scores[i] > value){
561+
for (let i = 0; i < 7; i++) {
562+
if (column_scores[i] > value) {
530563
value = column_scores[i];
531564
best_column = i;
532-
}
565+
}
533566
}
534567
// if best_column = -1, then that means all posible moves lead to certain loss
535-
if (best_column === -1){
536-
for (let i = 0; i < 7; i++){
537-
if (state.columns[i].fill < CONNECT_FOUR_ROW_COUNT){
568+
if (best_column === -1) {
569+
for (let i = 0; i < 7; i++) {
570+
if (state.columns[i].fill < CONNECT_FOUR_ROW_COUNT) {
538571
return i;
539572
}
540573
}
541-
}
574+
}
542575
return best_column;
543-
}
576+
};
544577

545-
// takes in ConnectFourGameState, returns best column for Codeybot to play in
546-
public getBestMove = (state : ConnectFourGameState): number => {
578+
// takes in ConnectFourGameState, returns best column for Codeybot to play in
579+
public getBestMove = (state: ConnectFourGameState): number => {
547580
return this.findBestColumn(state);
548581
};
549582
}

src/interaction-handlers/games/connectFour.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class ConnectFourHandler extends InteractionHandler {
6161
const status = await game.setStatus(game.state, result.sign - 1);
6262
if (status === ConnectFourGameStatus.Pending) {
6363
if (!game.state.player2Id) {
64-
let bestMove = game.getBestMove(game.state);
64+
const bestMove = game.getBestMove(game.state);
6565
updateColumn(game.state.columns[bestMove], game.state.player2Sign);
6666
game.setStatus(game.state, bestMove);
6767
}
@@ -78,4 +78,4 @@ export class ConnectFourHandler extends InteractionHandler {
7878
// async function sleep(ms: number): Promise<void> {
7979
// return new Promise(
8080
// (resolve) => setTimeout(resolve, ms));
81-
// }
81+
// }

0 commit comments

Comments
 (0)