runs, but not webserver
This commit is contained in:
@@ -14,6 +14,11 @@ tokio-tungstenite = "0.24"
|
|||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
leptos = { version = "0.6", features = ["csr"] }
|
||||||
|
leptos_axum = { version = "0.6" }
|
||||||
|
leptos_meta = { version = "0.6" }
|
||||||
|
leptos_router = { version = "0.6" }
|
||||||
|
protoss-bot-web = { path = "web" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
use crate::{
|
||||||
|
state::game_state::GameState,
|
||||||
|
utils::{build_manager, worker_management},
|
||||||
|
};
|
||||||
use rsbwapi::*;
|
use rsbwapi::*;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use crate::{state::game_state::GameState, utils::{build_manager, worker_management}};
|
|
||||||
|
|
||||||
fn draw_unit_ids(game: &Game) {
|
fn draw_unit_ids(game: &Game) {
|
||||||
for unit in game.get_all_units() {
|
for unit in game.get_all_units() {
|
||||||
@@ -47,6 +50,17 @@ impl AiModule for ProtosBot {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
println!("unit created: {:?}", unit.get_type());
|
println!("unit created: {:?}", unit.get_type());
|
||||||
|
|
||||||
|
// Check if the created unit is a building
|
||||||
|
if !unit.get_type().is_building() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(mut locked_state) = self.game_state.lock() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
build_manager::on_building_create(&unit, &mut locked_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_unit_morph(&mut self, _game: &Game, _unit: Unit) {}
|
fn on_unit_morph(&mut self, _game: &Game, _unit: Unit) {}
|
||||||
|
|||||||
@@ -3,14 +3,41 @@ mod state;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use bot::ProtosBot;
|
use bot::ProtosBot;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use state::game_state::GameState;
|
use state::game_state::GameState;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Starting RustBot...");
|
println!("Starting RustBot...");
|
||||||
|
|
||||||
let game_state = Arc::new(Mutex::new(GameState::default()));
|
let game_state = Arc::new(Mutex::new(GameState::default()));
|
||||||
|
|
||||||
|
// // Start the webserver in a separate thread
|
||||||
|
// std::thread::spawn(|| {
|
||||||
|
// let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
// rt.block_on(start_webserver());
|
||||||
|
// });
|
||||||
|
|
||||||
rsbwapi::start(move |_game| ProtosBot::new(game_state.clone()));
|
rsbwapi::start(move |_game| ProtosBot::new(game_state.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn start_webserver() {
|
||||||
|
use axum::Router;
|
||||||
|
use leptos::*;
|
||||||
|
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||||
|
use protoss_bot_web::App;
|
||||||
|
|
||||||
|
let conf = get_configuration(None).await.unwrap();
|
||||||
|
let leptos_options = conf.leptos_options;
|
||||||
|
let addr = leptos_options.site_addr;
|
||||||
|
let routes = generate_route_list(App);
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.leptos_routes(&leptos_options, routes, App)
|
||||||
|
.with_state(leptos_options);
|
||||||
|
|
||||||
|
println!("Web server listening on http://{}", &addr);
|
||||||
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||||
|
axum::serve(listener, app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use rsbwapi::{Game, Order, Player, UnitType};
|
use rsbwapi::{Game, Order, Player, Unit, UnitType};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::game_state::{BuildHistoryEntry, GameState, IntendedCommand},
|
state::game_state::{BuildHistoryEntry, GameState, IntendedCommand},
|
||||||
@@ -10,6 +10,27 @@ pub fn on_frame(game: &Game, player: &Player, state: &mut GameState) {
|
|||||||
try_start_next_build(game, player, state);
|
try_start_next_build(game, player, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_building_create(unit: &Unit, state: &mut GameState) {
|
||||||
|
// Find the build history entry associated with this building type
|
||||||
|
// and remove the probe's assignment
|
||||||
|
if let Some(entry) = state
|
||||||
|
.unit_build_history
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.find(|e| e.unit_type == Some(unit.get_type()))
|
||||||
|
{
|
||||||
|
if let Some(probe_id) = entry.assigned_unit_id {
|
||||||
|
// Remove the probe's intended command (PlaceBuilding order)
|
||||||
|
state.intended_commands.remove(&probe_id);
|
||||||
|
println!(
|
||||||
|
"Building {} started. Removed assignment for probe {}",
|
||||||
|
unit.get_type().name(),
|
||||||
|
probe_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn try_start_next_build(game: &Game, player: &Player, state: &mut GameState) {
|
fn try_start_next_build(game: &Game, player: &Player, state: &mut GameState) {
|
||||||
let Some(unit_type) = get_next_thing_to_build(game, player, state) else {
|
let Some(unit_type) = get_next_thing_to_build(game, player, state) else {
|
||||||
return;
|
return;
|
||||||
@@ -62,7 +83,8 @@ fn get_next_thing_to_build(game: &Game, player: &Player, state: &GameState) -> O
|
|||||||
|
|
||||||
if unit_type.is_building() {
|
if unit_type.is_building() {
|
||||||
let builder = find_builder_for_unit(player, *unit_type)?;
|
let builder = find_builder_for_unit(player, *unit_type)?;
|
||||||
let build_location = build_location_utils::find_build_location(game, &builder, *unit_type, 20);
|
let build_location =
|
||||||
|
build_location_utils::find_build_location(game, &builder, *unit_type, 20);
|
||||||
if build_location.is_none() {
|
if build_location.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -71,9 +93,9 @@ fn get_next_thing_to_build(game: &Game, player: &Player, state: &GameState) -> O
|
|||||||
candidates.push(*unit_type);
|
candidates.push(*unit_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates.into_iter().max_by_key(|unit_type| {
|
candidates
|
||||||
unit_type.mineral_price() + unit_type.gas_price()
|
.into_iter()
|
||||||
})
|
.max_by_key(|unit_type| unit_type.mineral_price() + unit_type.gas_price())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_need_more_supply(game: &Game, player: &Player) -> Option<UnitType> {
|
fn check_need_more_supply(game: &Game, player: &Player) -> Option<UnitType> {
|
||||||
@@ -92,7 +114,8 @@ fn check_need_more_supply(game: &Game, player: &Player) -> Option<UnitType> {
|
|||||||
|
|
||||||
if can_afford_unit(player, pylon_type) {
|
if can_afford_unit(player, pylon_type) {
|
||||||
if let Some(builder) = find_builder_for_unit(player, pylon_type) {
|
if let Some(builder) = find_builder_for_unit(player, pylon_type) {
|
||||||
let build_location = build_location_utils::find_build_location(game, &builder, pylon_type, 20);
|
let build_location =
|
||||||
|
build_location_utils::find_build_location(game, &builder, pylon_type, 20);
|
||||||
if build_location.is_some() {
|
if build_location.is_some() {
|
||||||
return Some(pylon_type);
|
return Some(pylon_type);
|
||||||
}
|
}
|
||||||
@@ -115,7 +138,12 @@ fn find_builder_for_unit(player: &Player, unit_type: UnitType) -> Option<rsbwapi
|
|||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_builder_to_construct(game: &Game, builder: &rsbwapi::Unit, unit_type: UnitType, state: &mut GameState) -> bool {
|
fn assign_builder_to_construct(
|
||||||
|
game: &Game,
|
||||||
|
builder: &rsbwapi::Unit,
|
||||||
|
unit_type: UnitType,
|
||||||
|
state: &mut GameState,
|
||||||
|
) -> bool {
|
||||||
let builder_id = builder.get_id();
|
let builder_id = builder.get_id();
|
||||||
|
|
||||||
if unit_type.is_building() {
|
if unit_type.is_building() {
|
||||||
@@ -180,8 +208,6 @@ fn count_units_of_type(player: &Player, _state: &GameState, unit_type: UnitType)
|
|||||||
.filter(|u| u.get_type() == unit_type)
|
.filter(|u| u.get_type() == unit_type)
|
||||||
.count() as i32;
|
.count() as i32;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
existing
|
existing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,33 +10,12 @@ pub fn assign_idle_workers_to_minerals(game: &Game, player: &Player, state: &mut
|
|||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// First, clean up workers that finished building
|
// Assign idle workers to mining
|
||||||
reassign_finished_builders(game, &workers, state);
|
|
||||||
|
|
||||||
// Then assign idle workers to mining
|
|
||||||
for worker in workers {
|
for worker in workers {
|
||||||
assign_worker_to_mineral(game, &worker, state);
|
assign_worker_to_mineral(game, &worker, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reassign_finished_builders(_game: &Game, workers: &[Unit], state: &mut GameState) {
|
|
||||||
for worker in workers {
|
|
||||||
let worker_id = worker.get_id();
|
|
||||||
|
|
||||||
if let Some(cmd) = state.intended_commands.get(&worker_id) {
|
|
||||||
if cmd.order == Order::PlaceBuilding {
|
|
||||||
let current_order = worker.get_order();
|
|
||||||
if worker.is_idle() && current_order != Order::PlaceBuilding && current_order != Order::ConstructingBuilding {
|
|
||||||
println!("Worker {} with order {:?} finished building, reassigning to minerals", worker_id, current_order);
|
|
||||||
state.intended_commands.remove(&worker_id);
|
|
||||||
}
|
|
||||||
} else if cmd.order == Order::Train && worker.is_idle() && !worker.is_training() {
|
|
||||||
state.intended_commands.remove(&worker_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_worker_to_mineral(game: &Game, worker: &Unit, state: &mut GameState) {
|
fn assign_worker_to_mineral(game: &Game, worker: &Unit, state: &mut GameState) {
|
||||||
let worker_id = worker.get_id();
|
let worker_id = worker.get_id();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user