Browse Source

filled out some game functions (untested)

main
Thomas Johnson 6 months ago
parent
commit
b04666f286
  1. 4
      src/index.html
  2. 135
      src/lib.rs
  3. 22
      src/server.rs

4
src/index.html

@ -17,7 +17,7 @@
<button id="strike">Attack</button>
<button id="wait">Wait</button>
<button id="capture">Capture</button>
<button id="hide">Hide signals</button>
<button id="hide_signals">Hide signals</button>
<button id="reveal">Reveal attacks</button>
<button id="invisible">Go invisible</button>
<button id="prepare">Prepare</button>
@ -74,4 +74,4 @@
</script>
</body>
</html>
</html>

135
src/lib.rs

@ -4,7 +4,7 @@ use serde::{Serialize, Deserialize};
pub type Intel = u32;
pub type PlayerId = usize;
#[derive(Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Location {
/// On starting a turn with a pending powerup, the additional intel is income.
pub pending_powerup: Option<Intel>,
@ -19,8 +19,9 @@ pub struct Location {
pub control: Option<PlayerId>,
}
#[derive(Default, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
pub struct Player {
pub alive: bool,
pub intel: Intel,
/// Cause intel-spending events to be vague to the enemy
pub hidden_signals: bool,
@ -94,26 +95,130 @@ impl Game {
}
}
pub fn strike(&mut self, pid: PlayerId) {
fn intel_reveal(&self, pid: PlayerId, update_queue: &mut Vec<(Option<PlayerId>, ClientUpdate)>, intel_kind: IntelKind) {
let kind = if self.players[pid].hidden_signals {
None
} else {
Some(intel_kind)
};
for pl in &self.players {
if pl.id != pid {
update_queue.push((Some(pl.id), ClientUpdate::Intel { by: Some(pid), kind } ));
}
}
}
pub fn strike(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
let mut update_queue = Vec::new();
for pl in 0..self.players.len() {
if pl != pid {
if self.players[pid].location == self.players[pl].location {
self.players[pl].alive = false;
update_queue.push((Some(pl), ClientUpdate::Death { by: pid, of: pl }));
update_queue.push((Some(pid), ClientUpdate::Death { by: pid, of: pl }));
}
if self.players[pl].visible_violence || !self.players[pl].alive {
update_queue.push((Some(pl), ClientUpdate::Strike { by: Some(pid), at: Some(self.players[pid].location) }));
} else {
update_queue.push((Some(pl), ClientUpdate::Strike { by: Some(pid), at: None }));
}
}
}
update_queue
}
pub fn wait(&mut self, pid: PlayerId) {
pub fn wait(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
vec![(None, ClientUpdate::WaitMove { by: Some(pid) })]
}
pub fn capture(&mut self, pid: PlayerId) {
pub fn capture(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
self.cities.node_weight_mut(self.players[pid].location).unwrap().control = Some(pid);
vec![(None, ClientUpdate::Capture { by: pid, at: self.players[pid].location })]
}
pub fn hide(&mut self, pid: PlayerId) {
pub fn hide_signals(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
// TODO: spend intel
// TODO: can't do this twice
let mut update_queue = Vec::new();
self.intel_reveal(pid, &mut update_queue, IntelKind::HideSignals);
self.players[pid].hidden_signals = true;
update_queue
}
pub fn reveal(&mut self, pid: PlayerId, loc: NodeIndex) {
pub fn reveal(&mut self, pid: PlayerId, reveal: Option<PlayerId>) -> Vec<(Option<PlayerId>, ClientUpdate)> {
// TODO: spend intel
let mut update_queue = Vec::new();
if let Some(reveal) = reveal {
if !self.players[reveal].invisible {
update_queue.push((Some(pid), ClientUpdate::Reveal { who: reveal, at: self.players[reveal].location }));
} else {
update_queue.push((Some(pid), ClientUpdate::RevealFailure { who: reveal } ));
}
} else {
for reveal in &self.players {
if reveal.id != pid {
if !reveal.invisible {
update_queue.push((Some(pid), ClientUpdate::Reveal { who: reveal.id, at: reveal.location }));
} else {
update_queue.push((Some(pid), ClientUpdate::RevealFailure { who: reveal.id } ));
}
}
}
}
self.intel_reveal(pid, &mut update_queue, IntelKind::HideSignals);
update_queue
}
pub fn invisible(&mut self, pid: PlayerId) {
pub fn invisible(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
// TODO: spend intel
let mut update_queue = Vec::new();
self.players[pid].invisible = true;
self.intel_reveal(pid, &mut update_queue, IntelKind::Invisible);
update_queue
}
pub fn prepare(&mut self, pid: PlayerId) {
pub fn prepare(&mut self, pid: PlayerId) -> Vec<(Option<PlayerId>, ClientUpdate)> {
// TODO: spend intel
let mut update_queue = Vec::new();
// TODO
self.intel_reveal(pid, &mut update_queue, IntelKind::Prepare);
update_queue
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ClientUpdate {
Death {
by: PlayerId,
of: PlayerId,
},
Strike {
by: Option<PlayerId>,
at: Option<NodeIndex>,
},
WaitMove { by: Option<PlayerId> },
Capture {
by: PlayerId,
at: NodeIndex,
},
Intel {
by: Option<PlayerId>,
kind: Option<IntelKind>,
},
Reveal {
who: PlayerId,
at: NodeIndex,
},
RevealFailure {
who: PlayerId,
},
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum IntelKind {
HideSignals,
Reveal,
Invisible,
Prepare,
}

22
src/server.rs

@ -82,12 +82,12 @@ async fn do_action(
let gm = state.lock().games.get(&gid).expect("no homie").clone();
let mut gm = gm.lock();
match body.as_ref() {
b"strike" => gm.strike(pid),
b"wait" => gm.wait(pid),
b"capture" => gm.capture(pid),
b"hide" => gm.hide(pid),
b"invisible" => gm.invisible(pid),
b"prepare" => gm.prepare(pid),
b"strike" => { gm.strike(pid); },
b"wait" => { gm.wait(pid); },
b"capture" => { gm.capture(pid); },
b"hide_signals" => { gm.hide_signals(pid); },
b"invisible" => { gm.invisible(pid); },
b"prepare" => { gm.prepare(pid); },
_ => match body.as_ref().split(|c| b':' == *c).collect::<Vec<_>>()[..] {
[b"move", to] => {
return HttpResponse::Ok().body(
@ -103,15 +103,11 @@ async fn do_action(
.to_string(),
);
}
[b"reveal", loc] => {
[b"reveal", who] => {
gm.reveal(
pid,
NodeIndex::new(
std::str::from_utf8(loc)
.expect("utf8")
.parse()
.expect("bad location"),
),
// TODO
None,
);
}
_ => return HttpResponse::InternalServerError().body("no such action"),

Loading…
Cancel
Save