vitogit / vue-chessboard

Chessboard vue component to load positions, create positions and see threats
http://vitomd.com/vue-chessboard-examples/
GNU General Public License v3.0
165 stars 49 forks source link

how to undo a move #38

Closed additional-pumpkin closed 2 years ago

additional-pumpkin commented 2 years ago

probably a stupid question but I tried this

    document.addEventListener('keydown', (event) => {
        if (event.key == "ArrowLeft")
        {
          chessboard.game.undo();
        }

and it says can't read undo of undefined

so how do I access chess js from chessground

vitogit commented 2 years ago

Probably you will need to extend the chessboard component to add new behavior. Here is an example. https://github.com/vitogit/vue-chessboard#extended-component-play-vs-random-ai

You access this.game to access the chess.js library and this.board to access the chessground.js

Something like

          // undo the move
          this.game.undo()
          // needed to redraw the new fen
          this.board.set({
            fen: this.game.fen()
          })
additional-pumpkin commented 2 years ago

ok so it doesn't seem to work idk why

<template>
  <div class="merida" id="app">
    <h1>Simple Chessboard with legal moves</h1>
    <chessboard/>
    <button @click="takeBack()">click me</button>

  </div>
</template>

<script>
import {chessboard} from 'vue-chessboard'
import './boardtheme.css'

export default {
  name: 'app',
  components: {
    chessboard
  },
  methods: {
    takeBack()
    {
        this.game.undo();
        this.board.set();
    }
  },
  mounted()
  {
    this.game.undo();
    this.board.set({
        fen: this.game.fen()
    })
  }
}

</script>

I get this error

>
warn @ vue.runtime.esm.js?2b0e:619
vue.runtime.esm.js?2b0e:1897 TypeError: Cannot read property 'undo' of undefined
    at VueComponent.mounted (App.vue?234e:48)
    at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1863)
    at callHook (vue.runtime.esm.js?2b0e:4235)
    at Object.insert (vue.runtime.esm.js?2b0e:3158)
    at invokeInsertHook (vue.runtime.esm.js?2b0e:6390)
    at Vue.patch [as __patch__] (vue.runtime.esm.js?2b0e:6609)
    at Vue._update (vue.runtime.esm.js?2b0e:3960)
    at Vue.updateComponent (vue.runtime.esm.js?2b0e:4081)
    at Watcher.get (vue.runtime.esm.js?2b0e:4495)
    at new Watcher (vue.runtime.esm.js?2b0e:4484)
additional-pumpkin commented 2 years ago

by the way I am a beginner to vue I use electron, webpack

vitogit commented 2 years ago

The goal of the library is just to show positions, so if you want to make something else you have to extend the component to access the internal methods.

Create a new .vue file like newboard.vue and try to make this example work first. This will create a new board called newboard and you can move pieces and the opponent will play random moves. I

  // newboard.vue
  <script>
  import { chessboard }  from 'vue-chessboard'

  export default {
    name: 'newboard',
    extends: chessboard,
    methods: {
      userPlay() {
        return (orig, dest) => {
          if (this.isPromotion(orig, dest)) {
            this.promoteTo = this.onPromotion()
          }
          this.game.move({from: orig, to: dest, promotion: this.promoteTo}) // promote to queen for simplicity
          this.board.set({
            fen: this.game.fen()
          })
          this.calculatePromotions()
          this.aiNextMove()
        };
      },
      aiNextMove() {
        let moves = this.game.moves({verbose: true})
        let randomMove = moves[Math.floor(Math.random() * moves.length)]
        this.game.move(randomMove)

        this.board.set({
          fen: this.game.fen(),
          turnColor: this.toColor(),
          movable: {
            color: this.toColor(),
            dests: this.possibleMoves(),
            events: { after: this.userPlay()},
          }
        });
      },
    },
    mounted() {
      this.board.set({
        movable: { events: { after: this.userPlay()} },
      })
    }
  }
  </script>

Then you use this new board . If you can make this work then I think you can manage to add the undo button.

<template>
  <div>
    <h1>Random play</h1>
    <newboard/>
  </div>
</template>

Or you can go to https://github.com/vitogit/vue-chessboard-examples/tree/master/src and check the example files (and try to make them work on your computer), the random play example is there

additional-pumpkin commented 2 years ago

I can undo it after a move but I don't understand how to do it with a button

I keep getting classlist undefined errors

additional-pumpkin commented 2 years ago

where is the source code for this website: https://tacticalchess.vitomd.com/ maybe it would help

because it is the only website I can find made with chessboard that has an undo feature

vitogit commented 2 years ago

https://tacticalchess.vitomd.com/

Is not public and use an old version different than this, but the code is like this

There is a button <a @click="takeBack" class="button">Take back</a>

And there is the method

    takeBack() {
      this.game.undo()
      this.game.undo()

        this.board.set({
          fen: this.game.fen()
        })
    },

Show me your code to see what's the problem.

additional-pumpkin commented 2 years ago

so that is what I tried but I got the classlist undefined error. Then I tried to access the this.chess in a child component and I got a new instance and tried to somehow send the original instance to the child but failed

I will post the code, I lost it after windows 11 did some secure boot stuff and my efi partition was no more. I will write it again soon and post. I miss linux

additional-pumpkin commented 2 years ago

i still don't understand how to do it

app.vue

<template>
  <div id="app">
    <newboard/>
    <button @click="undo">undo</button>

  </div>
</template>

<script>
import 'vue-chessboard/dist/vue-chessboard.css'
import newboard from './components/chessboard.vue'

export default {
  name: 'app',
  components: {
    newboard,
  },
  data () {
    return {
      currentFen: '',
      positionInfo: null
    }
  },
  methods: {
    undo(){
      this.game.undo()
    },
  },
}
</script>

chessboard.js


  <script>
  import { chessboard }  from 'vue-chessboard'

  export default {
    name: 'newboard',
    extends: chessboard,
    methods: {
      userPlay() {
        return (orig, dest) => {
          if (this.isPromotion(orig, dest)) {
            this.promoteTo = this.onPromotion()
          }
          this.game.move({from: orig, to: dest, promotion: this.promoteTo}) // promote to queen for simplicity
          this.board.set({
            fen: this.game.fen()
          })
          this.calculatePromotions()
          this.aiNextMove()
        };
      },
      aiNextMove() {
        let moves = this.game.moves({verbose: true})
        let randomMove = moves[Math.floor(Math.random() * moves.length)]
        this.game.move(randomMove)

        this.board.set({
          fen: this.game.fen(),
          turnColor: this.toColor(),
          movable: {
            color: this.toColor(),
            dests: this.possibleMoves(),
            events: { after: this.userPlay()},
          }
        });
      },
    },
    mounted() {
      this.board.set({
        movable: { events: { after: this.userPlay()} },
      })
    }
  }
  </script>

this is the error

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'undo' of undefined"

found in

---> <App> at src/App.vue
       <Root>
vue.runtime.esm.js?2b0e:1897 TypeError: Cannot read property 'undo' of undefined
    at VueComponent.undo (App.vue?234e:26)
    at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1863)
    at HTMLButtonElement.invoker (vue.runtime.esm.js?2b0e:2188)
    at HTMLButtonElement.original._wrapper (vue.runtime.esm.js?2b0e:6961)
vitogit commented 2 years ago

You are missing the comm between the components. It's been a while since I use Vue, probably the new version is different but I added a new "undo" example using a bus event.

You can check the example (Extended Component (Play vs random AI with undos). ) https://vitogit.github.io/vue-chessboard-examples/

And the code is in this commit https://github.com/vitogit/vue-chessboard-examples/commit/355157b9c1ae101b1a824bcb36003c204165af84