From 73bbca17aa9e050f515c92c6fb92e5786fb4562a Mon Sep 17 00:00:00 2001 From: Amjad Jibon Date: Tue, 20 Aug 2024 00:53:22 +0800 Subject: [PATCH 1/2] implement undo method to revert last move in game --- game.go | 13 +++++++++++++ game_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/game.go b/game.go index 67f7cd2..9f7ec89 100644 --- a/game.go +++ b/game.go @@ -195,6 +195,19 @@ func (g *Game) Moves() []*Move { return append([]*Move(nil), g.moves...) } +// Undo reverts the last move and restores the previous game state. +func (g *Game) Undo() (*Move, error) { + if len(g.moves) == 0 { + return nil, errors.New("chess: no moves to undo") + } + lastMove := g.moves[len(g.moves)-1] + g.moves = g.moves[:len(g.moves)-1] + g.positions = g.positions[:len(g.positions)-1] + g.pos = g.positions[len(g.positions)-1] + g.updatePosition() + return lastMove, nil +} + // Comments returns the comments for the game indexed by moves. func (g *Game) Comments() [][]string { return append([][]string(nil), g.comments...) diff --git a/game_test.go b/game_test.go index ec60e3e..eb12b08 100644 --- a/game_test.go +++ b/game_test.go @@ -110,6 +110,37 @@ func TestThreeFoldRepetition(t *testing.T) { } } +func TestUndo(t *testing.T) { + g := NewGame() + _, err := g.Undo() + if err == nil { + t.Fatal("should require at least one move before undo") + } + + moves := []string{ + "Nf3", "Nf6", "Ng1", "Ng8", + } + + for _, m := range moves { + if err = g.MoveStr(m); err != nil { + t.Fatal(err) + } + } + + lastMove, err := g.Undo() + if err != nil { + t.Fatal(err) + } + + if lastMove.String() != "f6g8" { + t.Fatal("last move should be f6g8") + } + + if g.moves[len(g.moves)-1].String() != "f3g1" { + t.Fatal("last move should be f3g1") + } +} + func TestInvalidThreeFoldRepetition(t *testing.T) { g := NewGame() moves := []string{ From eb01031b7780b35f993c55975f01d0d89c15f4fb Mon Sep 17 00:00:00 2001 From: silkrow Date: Tue, 3 Sep 2024 15:38:39 -0500 Subject: [PATCH 2/2] modified updatePosition function to support Undo feature, added test case for TestUndo --- game.go | 4 ++++ game_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/game.go b/game.go index 9f7ec89..aefc4b4 100644 --- a/game.go +++ b/game.go @@ -391,7 +391,11 @@ func (g *Game) updatePosition() { if g.pos.Turn() == White { g.outcome = BlackWon } + } else if method == NoMethod { + g.method = NoMethod + g.outcome = NoOutcome } + if g.outcome != NoOutcome { return } diff --git a/game_test.go b/game_test.go index eb12b08..51221e2 100644 --- a/game_test.go +++ b/game_test.go @@ -139,6 +139,30 @@ func TestUndo(t *testing.T) { if g.moves[len(g.moves)-1].String() != "f3g1" { t.Fatal("last move should be f3g1") } + + g = NewGame() + moves = []string{ + "f4", "e6", "g4", "Qh4", + } + + for _, m := range moves { + if err = g.MoveStr(m); err != nil { + t.Fatal(err) + } + } + + lastMove, err = g.Undo() + if err != nil { + t.Fatal(err) + } + + if err = g.MoveStr("h6"); err != nil { + t.Fatal(err) + } + if g.Outcome() != NoOutcome { + t.Fatal("unexpected game outcome") + } + } func TestInvalidThreeFoldRepetition(t *testing.T) {