Skip to content

Tristan/lua bot#15

Open
TristanStreich wants to merge 11 commits intomainfrom
tristan/luaBot
Open

Tristan/lua bot#15
TristanStreich wants to merge 11 commits intomainfrom
tristan/luaBot

Conversation

@TristanStreich
Copy link
Copy Markdown
Collaborator

Description

  1. Allows creation of bots written in lua.
  2. Adds extra page to play against bot step where you select bot
  3. Adds page to optionally edit bots that have already been saved

In addition mlua was missing a c dependency (I think) from the debian slim image so I changed it to the full image in the docker and the ci

Test

Done lots of clicking around to double check non of the existing features are broken but a lot of shared logic was changed so let me know if you run into any issues.

I have made a few example bots you can play against here

TODO:

Stateful Bots

Lua bots are stateless right now so adding a todo to allow for stateful bots. For example this bot would not work as inteded and would always just choose the first move.

MyStatefulBot = {
   counter = 1
}


function MyStatefulBot:chooseMove(_chessGame, legalMoves)
     local chosenMove = legalMoves[self.counter % #legalMoves]
     self.counter = self.counter + 1
     return chosenMove
end

return MyStatefulBot

Persistant Bots

Bots are just stored in memory right now so are lost on server restart. Will need to add a way to persist them. First by writing to disk but eventually to something like s3.

Bot Vs Bot

Bot vs bot is still hard coded to use RustRandomBot will need to allow users to select the lua bots to play them against each other.

@CarterMcClellan
Copy link
Copy Markdown
Owner

CarterMcClellan commented Jan 14, 2024

Looks like build failed

edit: looks all good

@TristanStreich
Copy link
Copy Markdown
Collaborator Author

TristanStreich commented Jan 14, 2024

I think the build was fixed in the last commit.

I needed to change the base image of the ci


pub struct PlayerGame {
bot: Box<dyn ChooseMove + Send + Sync>,
bot: Box<dyn ChooseMove>,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of interesting how different player vs bot looks. I guess something more like

async fn player_vs_bot(game: Arc<Game>, player_moves_channel: WebsocketThingy<Move>, bot: Arc<dyn ChooseMove>) {
    info!("Player vs Bot Started...");

    loop {
        let player_move = player_moves_channel.recv().await;

        game.make_move(&player_move);

        let legal_moves = game.get_legal_moves();

        let bot_move = bot.choose_move(&game, &legal_moves);

        game.make_move(&bot_move);
    }
}

Would be less efficient because you would be using a websocket to recieve moves from the player (which I assume uses a socket and a tokio thread??), and a tokio blocking thread to await/ update the game state.

Where as doing this the more traditional http server route there is basically no blocking/ stalls and no need to use tokio threads to await move updates from the player.

But pretty interesting how these code paths which do pretty similar things came out functionally pretty different

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this is more or less efficient. Since this is async we could even use this approach in a regular tokio spawn. I used normal HTTP purely due to my familiarity with it

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am guessing the only downside to this is it is more demanding of the client network


impl<C: 'static + ChooseMove + Clone> ToChooseMove for C {
fn to_choose_move(&self) -> Box<dyn ChooseMove> {
Box::new(self.clone())
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to double check, this is for so that we can store anything which implements ChooseMove in our hashmap?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah so this is kinda messy but the idea is that we have a hashmap of bots that have been created we want to make a new instance of the bot so that if the bot is stateful there is a seperate instance for each active bot. So we just need to clone the Box<dyn ChooseMove> out of the struct but just adding ChooseMove: Clone as a trait bound makes it no longer object safe (not fully sure why that is. Still new to dynamic trait objects). This is kinda just a way to get around that limitation.

That all being said, none of the bots are stateful so we don't strictly need this. We could just just Arc<dyn ChooseMove> in the hashmap and thene clone the arc. Then all active bots share the same underlying state but it does not matter right now.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! The premise of a stateful bot is pretty interesting, are you envisioning something statistical like a Neural Network governing the moves made by the agent?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have anything in particular in mind. I'm just trying to allow for as much freedom in design as possible.

For example one could memosize heuristics for positions between calls to chooseMove

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants