1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use crate::{State, TILES};
use anyhow::{Result, anyhow};
use hurrycurry_protocol::{
TileIndex,
glam::{IVec2, ivec2},
};
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
hash::RandomState,
};
#[rustfmt::skip]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MapDecl {
map: Vec<String>,
tiles: HashMap<char, String>,
items: HashMap<char, String>,
collider: Vec<String>,
walkable: Vec<String>,
chef_spawn: char,
customer_spawn: char,
score_baseline: i64,
}
pub fn export_state(state: &State) -> String {
let mut cmin = IVec2::MAX;
let mut cmax = IVec2::MIN;
for pos in state.tiles.keys().copied() {
cmin = cmin.min(pos);
cmax = cmax.max(pos);
}
let mut map = Vec::new();
let mut tiles = HashMap::new();
let mut collider = HashSet::new();
let mut walkable = HashSet::new();
for y in cmin.y..=cmax.y {
let mut line = String::new();
for x in cmin.x..=cmax.x {
let p = ivec2(x, y);
line.push(if let Some(t) = state.tiles.get(&p) {
let c = if p == state.chef_spawn {
'~'
} else if p == state.customer_spawn {
'!'
} else {
TILES[t.0].1
};
if TILES[t.0].2 == 2 {
collider.insert(TILES[t.0].0.to_string());
}
if TILES[t.0].2 == 1 {
walkable.insert(TILES[t.0].0.to_string());
}
tiles.insert(c, TILES[t.0].0.to_string());
c
} else {
' '
})
}
map.push(line);
}
let decl: MapDecl = MapDecl {
map,
tiles,
items: HashMap::new(),
collider: collider.into_iter().collect(),
walkable: walkable.into_iter().collect(),
chef_spawn: '~',
customer_spawn: '!',
score_baseline: 200,
};
serde_yml::to_string(&decl).unwrap()
}
pub fn import_state(state: &mut State, s: &str) -> Result<()> {
let decl: MapDecl = serde_yml::from_str(s)?;
let name_to_tile = HashMap::<_, _, RandomState>::from_iter(
TILES
.iter()
.enumerate()
.map(|(i, (name, _, _))| ((*name).to_owned(), i)),
);
for (y, line) in decl.map.iter().enumerate() {
for (x, char) in line.chars().enumerate() {
let pos = ivec2(x as i32, y as i32);
if char == ' ' {
continue;
}
if char == decl.customer_spawn {
state.customer_spawn = pos;
}
if char == decl.chef_spawn {
state.chef_spawn = pos;
}
let tile = decl
.tiles
.get(&char)
.ok_or(anyhow!("char undefined {char:?}"))?;
let tile = name_to_tile
.get(tile)
.ok_or(anyhow!("unknown tile {tile:?}"))?;
state.set_tile(pos, TileIndex(*tile));
}
}
Ok(())
}
|