#![allow(unused)]
pub mod api;
mod ffi;
fn main() {}
macro_rules! d {
($val:expr) => {
unsafe {
if AID == 2
{
dbg!($val)
} else {
$val
}
}
};
}
#[derive(Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd)]
struct Plateau(Vec<Case>, Vec<Nain>);
impl Plateau {
fn idx(&self, pos: Position) -> &Case {
if pos.in_bounds() {
unsafe {
self.0
.get_unchecked(pos.i as usize * api::TAILLE_MINE as usize + pos.j as usize)
}
} else {
&Case::Obs
}
}
fn idx_mut(&mut self, pos: Position) -> &mut Case {
if pos.in_bounds() {
unsafe {
self.0
.get_unchecked_mut(pos.i as usize * api::TAILLE_MINE as usize + pos.j as usize)
}
} else {
d!(pos);
panic!()
}
}
}
use api::{CaseType, Direction, Erreur, Nain, Position, INVALID_POSITION};
use std::os::raw::{c_double, c_int, c_void};
static mut AID: i32 = -1;
static mut ATA: Position = INVALID_POSITION;
static mut BID: i32 = -1;
static mut BTA: Position = INVALID_POSITION;
#[derive(Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd)]
enum Case {
Air {
nains: Vec<usize>,
corde: bool,
},
Pie {
res: i32,
pri: i32,
},
Obs,
}
impl Erreur {
fn into(self) -> Result<(), Erreur> {
match self {
Erreur::Ok => Ok(()),
_ => Err(self),
}
}
}
impl Position {
fn in_bounds(self) -> bool {
self.i >= 0 && self.i < api::TAILLE_MINE && self.j >= 0 && self.j < api::TAILLE_MINE
}
fn to(mut self, dir: Direction) -> Self {
if self != INVALID_POSITION {
match dir {
Direction::Haut => self.i -= 1,
Direction::Bas => self.i += 1,
Direction::Gauche => self.j -= 1,
Direction::Droite => self.j += 1,
Direction::ErreurDirection => self = INVALID_POSITION,
}
};
self
}
}
fn gravity(pla: &mut Plateau, posa: Position) {
let (non_tombe, tombe): (Vec<usize>, Vec<_>) = match pla.idx(posa) {
Case::Air { nains, .. } => nains.iter().partition(|&&nain| pla.1[nain].accroche),
_ => return,
};
let mut chu = 0;
let mut posb = posa;
while let Case::Air { .. } = pla.idx(posb.to(Direction::Bas)) {
chu += 1;
posb = posb.to(Direction::Bas);
}
let deg = match chu {
h if h < 4 => 0,
h => 1 << (h - 4),
};
for &i in &tombe {
let mut nain = pla.1[i];
nain.vie -= deg;
}
match pla.idx_mut(posa) {
Case::Air { nains, .. } => {
*nains = non_tombe;
}
_ => panic!(),
};
match pla.idx_mut(posb) {
Case::Air { nains, .. } => nains.extend(tombe),
_ => panic!(),
};
}
fn cout_de_deplacement(nain: Nain, dir: Direction) -> i32 {
if nain.accroche {
api::COUT_ESCALADER
} else {
api::COUT_DEPLACEMENT
}
}
fn accrocher(nain: &mut Nain, accroche: bool) -> Result<(), Erreur> {
if accroche && !nain.accroche {
api::agripper(nain.nid).into()?;
nain.pa -= api::COUT_AGRIPPER;
} else if !accroche && nain.accroche {
api::lacher(nain.nid).into()?;
}
nain.accroche = accroche;
Ok(())
}
fn deplacer(nain_id: usize, pla: &mut Plateau, dir: Direction) -> Result<(), Erreur> {
let nain = pla.1[nain_id];
let posa = nain.pos;
let posb = posa.to(dir);
{
let nain = &mut pla.1[nain_id];
api::deplacer(nain.nid, dir).into()?;
nain.pm -= cout_de_deplacement(*nain, dir);
nain.pos = posb;
}
gravity(pla, posb);
Ok(())
}
fn miner(nain_id: usize, pla: &mut Plateau, dir: Direction) -> Result<(), Erreur> {
let nain = pla.1[nain_id];
api::miner(nain.nid, dir).into()?;
let posb = nain.pos.to(dir);
if !posb.in_bounds() {
return Erreur::HorsLimites.into();
}
let pri = {
let case = pla.idx_mut(posb);
let (b, pri) = match case {
Case::Pie { res, pri } => {
*res -= 1;
(*res == 0, *pri)
}
_ => (false, 0),
};
if b {
*case = Case::Air {
nains: Vec::new(),
corde: false,
};
}
pri
};
let nain = &mut pla.1[nain_id];
nain.butin = std::cmp::min(api::BUTIN_MAX, nain.butin + pri);
nain.pa -= api::COUT_MINER;
Ok(())
}
fn deplacer_smart(nain_id: usize, pla: &mut Plateau, dir: Direction) -> Result<(), Erreur> {
let nain = pla.1[nain_id];
let posb = nain.pos.to(dir);
match api::type_case(posb) {
CaseType::Granite => {
{
let nain = &mut pla.1[nain_id];
accrocher(nain, false)?;
}
miner(nain_id, pla, dir)
}
CaseType::Libre => {
{
let nain = &mut pla.1[nain_id];
accrocher(nain, true)?;
}
deplacer(nain_id, pla, dir)
}
_ => Err(Erreur::ObstacleMur),
}
}
fn aller_tmp(nain_id: usize, pla: &mut Plateau, arr: Position) {
let nain = pla.1[nain_id];
for i in (0..1000) {
let che = api::chemin(nain.pos, arr);
if !che.is_empty() && deplacer_smart(nain_id, pla, che[0]).is_err() {
break;
}
}
}
fn plateau() -> Plateau {
let info_nains: Vec<_> = (0..api::NB_NAINS)
.map(|nid| api::info_nain(api::moi(), nid))
.chain((0..api::NB_NAINS).map(|nid| api::info_nain(api::adversaire(), nid)))
.collect();
let mut res: Plateau = Plateau(
(0..api::TAILLE_MINE * api::TAILLE_MINE)
.map(|ij| {
let pos = Position {
i: ij / api::TAILLE_MINE,
j: ij % api::TAILLE_MINE,
};
match api::type_case(pos) {
CaseType::Libre => Case::Air {
corde: false,
nains: Vec::new(),
},
CaseType::Granite => Case::Pie { res: 1, pri: 0 },
_ => Case::Obs,
}
})
.collect(),
info_nains.clone(),
);
for pos in api::liste_minerais() {
let inf = api::info_minerai(pos);
*res.idx_mut(pos) = Case::Pie {
res: inf.resistance,
pri: inf.rendement,
}
}
for (i, nain) in info_nains
.iter()
.filter(|nain| nain.pos.in_bounds())
.enumerate()
{
if let Case::Air { nains, .. } = res.idx_mut(nain.pos) {
nains.push(i)
}
}
res
}
fn partie_init() {
unsafe {
AID = api::moi();
BID = api::adversaire();
ATA = api::position_taverne(AID);
BTA = api::position_taverne(BID);
}
}
fn jouer_tour() {
let (aid, bid) = unsafe { (AID, BID) };
let tour = api::tour_actuel();
let asco = api::score(aid);
let bsco = api::score(bid);
let mut pla = plateau();
for _ in 0..1000 {
plateau().clone();
}
d!(())
}
fn partie_fin() {
}