/* Hurry Curry! - a game about cooking Copyright 2024 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #![feature(isqrt)] pub mod algos; pub mod pathfinding; use anyhow::Result; use clap::Parser; use hurrycurry_client_lib::{network::sync::Network, Game}; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, PacketC, PacketS, PlayerID, }; use log::warn; use std::{thread::sleep, time::Duration}; #[derive(Default, Clone, Copy)] pub struct BotInput { direction: Vec2, boost: bool, interact: Option, } pub trait BotAlgo { fn tick(&mut self, me: PlayerID, game: &Game, dt: f32) -> BotInput; } #[derive(Parser)] struct Args { algo: String, address: String, } fn main() -> Result<()> { env_logger::init_from_env("LOG"); rustls::crypto::ring::default_provider() .install_default() .unwrap(); let args = Args::parse(); let algo = args.algo.to_owned(); let init_algo = move || -> Box { match algo.as_str() { "test" => Box::new(algos::Test::default()), "simple" => Box::new(algos::Simple::default()), "waiter" => Box::new(algos::Waiter::default()), _ => panic!("unknown algo {algo:?}"), } }; let mut network = Network::connect(&args.address)?; let mut game = Game::default(); network.queue_out.push_back(PacketS::Join { name: "bot".to_string(), character: 1, }); let mut bots = Vec::new(); loop { let dt = 1. / 50.; network.poll()?; while let Some(packet) = network.queue_in.pop_front() { match &packet { PacketC::Joined { id } => bots.push(BotDriver { id: *id, interacting: false, state: init_algo(), }), PacketC::Error { message } => { warn!("server error message: {message}"); } _ => (), } game.apply_packet(packet); } for b in &mut bots { let BotInput { direction, boost, interact, } = b.state.tick(b.id, &game, dt); if interact.is_some() != b.interacting { b.interacting = interact.is_some(); network.queue_out.push_back(PacketS::Interact { player: b.id, pos: interact, }) } network.queue_out.push_back(PacketS::Movement { player: b.id, dir: direction, boost, pos: None, }); } sleep(Duration::from_secs_f32(dt)); } } pub struct BotDriver { pub interacting: bool, id: PlayerID, state: Box, }