Cargo clippy fixes

Did cargo clippy fixes
Added github workflows
This commit is contained in:
Uttarayan Mondal
2021-03-15 17:30:10 +05:30
parent 8bc7770bf3
commit 5a9e2a85c1
11 changed files with 481 additions and 106 deletions
+65 -68
View File
@@ -1,32 +1,43 @@
extern crate rand;
use crate::settings::Config;
use core::iter::Iterator;
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::collections::LinkedList;
use std::ops::Sub;
use std::thread::sleep;
use std::time::Duration;
#[derive(Debug)]
#[derive(Serialize, Deserialize, Clone, Copy)]
#[serde(tag = "type", content = "value")]
pub enum Difficulty {
Linear(f32),
Flat,
}
#[derive(Debug, Clone, Copy)]
pub enum Direction {
Up,
Down,
Left,
Right,
}
impl Copy for Direction {}
impl Clone for Direction {
fn clone(&self) -> Self {
*self
}
}
impl PartialEq for Direction {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(&Self::Up, &Self::Up) => true,
(&Self::Down, &Self::Down) => true,
(&Self::Left, &Self::Left) => true,
(&Self::Right, &Self::Right) => true,
_ => false,
}
// match (self, other) {
// (&Self::Up, &Self::Up) => true,
// (&Self::Down, &Self::Down) => true,
// (&Self::Left, &Self::Left) => true,
// (&Self::Right, &Self::Right) => true,
// _ => false,
// }
matches!(
(self, other),
(&Self::Up, &Self::Up)
| (&Self::Down, &Self::Down)
| (&Self::Left, &Self::Left)
| (&Self::Right, &Self::Right)
)
}
}
@@ -41,46 +52,29 @@ impl Direction {
}
}
#[derive(Debug)]
// impl std::fmt::Debug for Direction {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// // write!(f,)
// write!(
// f,
// "{}",
// match *self {
// Self::Up => (),
// _ => (),
// }
// );
// }
// }
pub enum CellType {
Food,
Snake,
Empty,
// Empty,
}
#[derive(Debug)]
pub struct Cell {
line: u32,
col: u32,
ctype: CellType,
_ctype: CellType,
}
impl PartialEq for Cell {
fn eq(&self, other: &Cell) -> bool {
if (self.line == other.line) && (self.col == other.col) {
return true;
} else {
return false;
}
(self.line == other.line) && (self.col == other.col)
}
}
impl Sub for Cell {
type Output = (i32, i32);
fn sub(self, rhs: Cell) -> (i32, i32) {
return (
(
self.line as i32 - rhs.line as i32,
self.col as i32 - rhs.col as i32,
);
)
}
}
impl Cell {
@@ -88,7 +82,7 @@ impl Cell {
Cell {
line: l,
col: c,
ctype: t,
_ctype: t,
}
}
pub fn random(lines: u32, cols: u32) -> Cell {
@@ -100,16 +94,16 @@ impl Cell {
)
}
pub fn posyx(&self) -> (u32, u32) {
return (self.line, self.col);
(self.line, self.col)
}
pub fn posy(&self) -> u32 {
return self.line;
self.line
}
pub fn posx(&self) -> u32 {
return self.col;
self.col
}
pub fn chtype(&mut self, ctype: CellType) {
self.ctype = ctype;
pub fn _chtype(&mut self, ctype: CellType) {
self._ctype = ctype;
}
pub fn is_adjacent(&self, other: &Cell) -> Option<Direction> {
match *self - *other {
@@ -135,17 +129,20 @@ impl Clone for Cell {
}
}
#[derive(Debug)]
enum FailState {
Wall,
Snake,
}
#[derive(Debug)]
enum GameState {
Failed(FailState),
Ready,
// Playing,
}
#[derive(Debug)]
pub struct Board {
maxlines: u32,
maxcols: u32,
@@ -165,10 +162,9 @@ impl Board {
}
pub fn check_collision(&mut self, snake: &Snake) -> bool {
let (snake_line, snake_col): (u32, u32) = snake.posyx();
if (snake_line >= self.maxlines - 1)
|| (snake_col >= self.maxcols - 1)
|| (snake_line <= 0)
|| (snake_col <= 0)
if (snake_line >= self.maxlines - 1) || (snake_col >= self.maxcols - 1)
// || (snake_line <= 0)
// || (snake_col <= 0)
{
self.gamestate = GameState::Failed(FailState::Wall);
return true;
@@ -182,17 +178,13 @@ impl Board {
return true;
}
}
return false;
false
}
pub fn check_food(&self, snake: &Snake) -> bool {
if self.food_posyx() == snake.posyx() {
return true;
} else {
return false;
}
self.food_posyx() == snake.posyx()
}
pub fn food_posyx(&self) -> (u32, u32) {
return self.food.posyx();
self.food.posyx()
}
// pub fn food_posy(&self) -> u32 {
// return self.food.line;
@@ -205,11 +197,11 @@ impl Board {
pub fn spawn_food(&mut self, snake: &Snake) {
let mut food: Cell = Cell::random(self.maxlines, self.maxcols);
let mut spawned_food = false;
while spawned_food != true {
while !spawned_food {
// check for colliosions with the snake body until a free spot is found and spawn the food there
spawned_food = true;
let mut snake_iter = snake.iter();
for snake_cell in snake_iter.next() {
let snake_iter = snake.iter();
for snake_cell in snake_iter {
if *snake_cell == food {
// O(n) ; I think this is nessacary/ I don't know how to reduce the order
// if food collides with the snake body then set food to a new random position and set spawned food to false
@@ -228,26 +220,27 @@ pub struct Snake {
head: Cell,
body: LinkedList<Cell>,
direction: Direction,
difficulty: Difficulty,
grow: bool,
speed: u32,
last_tail: Option<Cell>,
}
impl Snake {
pub fn new(head: Cell) -> Snake {
pub fn new(head: Cell, config: &Config) -> Snake {
let mut temp_body: LinkedList<Cell> = LinkedList::new();
temp_body.push_front(head);
Snake {
head,
body: temp_body,
// length: 1,
difficulty: config.difficulty,
direction: Direction::Right,
grow: false,
speed: 15,
grow: true,
speed: config.speed,
last_tail: Some(head),
}
}
pub fn posyx(&self) -> (u32, u32) {
return (self.head.line, self.head.col);
(self.head.line, self.head.col)
}
pub fn smove(&mut self, _direction: Direction) {
// smove because move is already a keyword
@@ -257,7 +250,7 @@ impl Snake {
} else {
direction = _direction
}
if self.grow == false {
if !self.grow {
self.last_tail = Some(self.body.pop_back().unwrap());
// self.grow = false;
@@ -285,16 +278,20 @@ impl Snake {
sleep(Duration::from_millis((1000 / self.speed) as u64));
self.smove(self.direction);
}
pub fn scale_difficulty(&mut self) {
match self.difficulty {
Difficulty::Flat => (),
Difficulty::Linear(scale) => self.speed = (self.speed as f32 * scale) as u32,
}
}
pub fn grow(&mut self) {
self.scale_difficulty();
self.grow = true;
}
pub fn iter(&self) -> impl Iterator<Item = &Cell> {
return self.body.iter();
self.body.iter()
}
pub fn remove(&self) -> Option<Cell> {
return self.last_tail;
}
pub fn set_speed(&mut self, speed: u32) {
self.speed = speed;
self.last_tail
}
}
+8 -5
View File
@@ -27,6 +27,11 @@ pub fn destroy_window(win: WINDOW) {
delwin(win); // delete the window
}
pub fn clear_window(win: WINDOW) {
wmove(win, 0, 0);
wclrtobot(win);
}
pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
// let mut snake_iter = snake.iter();
let (mut prev, mut current, _next): (&Cell, &Cell, &Cell);
@@ -45,12 +50,10 @@ pub fn draw_snake(snake: &Snake, game_win: WINDOW) {
prev.posx() as i32,
&format!("{}", std::char::from_u32(0x0298).unwrap_or('O')),
);
match snake.remove() {
Some(tail) => {
mvwaddstr(game_win, tail.posy() as i32, tail.posx() as i32, " ");
}
None => (),
if let Some(tail) = snake.remove() {
mvwaddstr(game_win, tail.posy() as i32, tail.posx() as i32, " ");
}
let _current = snake_iter.next();
current = match _current {
Some(cell) => cell,
+24 -15
View File
@@ -1,24 +1,28 @@
mod backend;
mod frontend;
use crate::menu;
use crate::settings::Config;
// use ncurses::*;
pub use backend::Difficulty;
use backend::{Board, Cell, Snake};
use ncurses::{
getmaxyx, nodelay, stdscr, wgetch, wrefresh, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_UP, WINDOW,
};
pub fn start() {
pub fn start(config: &Config) {
let (mut mlines, mut mcols): (i32, i32) = (0, 0);
let game_win: WINDOW;
let mut ch: i32;
let (vmargin, hmargin): (u32, u32) = (5, 10);
getmaxyx(stdscr(), &mut mlines, &mut mcols);
game_win = frontend::game_window(mlines as u32, mcols as u32, vmargin, hmargin);
let mut snake = Snake::new(Cell::new(
mlines as u32 / 2 - vmargin,
mcols as u32 / 2 - hmargin,
backend::CellType::Snake,
)); //Initialise snake in the middle of the screen
let mut snake = Snake::new(
Cell::new(
mlines as u32 / 2 - vmargin,
mcols as u32 / 2 - hmargin,
backend::CellType::Snake,
),
config,
); //Initialise snake in the middle of the screen
let mut board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2);
nodelay(game_win, true);
loop {
@@ -46,15 +50,20 @@ pub fn start() {
//112 is keycode for 'p'
0 => (), //resume
1 => {
snake = Snake::new(Cell::new(
mlines as u32 / 2,
mcols as u32 / 2,
backend::CellType::Snake,
)); //Initialise snake in the middle of the screen
board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2);
} //restart
snake = Snake::new(
Cell::new(
mlines as u32 / 2 - vmargin,
mcols as u32 / 2 - hmargin,
backend::CellType::Snake,
),
config,
); //Initialise snake in the middle of the screen
board = Board::new(mlines as u32 - vmargin * 2, mcols as u32 - hmargin * 2); //restart
frontend::clear_window(game_win);
}
2 => break, //exit
_ => (), //other charachters just in case
_ => (), //other charachters just in case
}
wrefresh(game_win);
nodelay(game_win, true);
+4 -1
View File
@@ -2,6 +2,7 @@ extern crate ncurses;
mod game;
mod highscore;
mod menu;
mod settings;
// use game::{Cell, Snake};
// use ncurses::*;
use ncurses::{
@@ -12,6 +13,7 @@ use ncurses::{
fn main() {
// let (lines, cols): (i32, i32) = (0, 0);
setlocale(LcCategory::all, "");
let config = settings::Config::new().unwrap();
initscr();
raw();
keypad(stdscr(), true);
@@ -27,11 +29,12 @@ fn main() {
}
loop {
match menu::main_menu_control() {
0 => game::start(),
0 => game::start(&config),
1 => highscore::show(),
_ => break,
}
}
refresh();
endwin();
config.write();
}
+77
View File
@@ -0,0 +1,77 @@
extern crate dirs;
extern crate serde;
// extern crate serde_derive;
extern crate toml;
use serde::{Deserialize, Serialize};
// use serde_derive::{Deserialize, Serialize};
use crate::game::Difficulty;
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;
use std::thread::sleep;
#[derive(Serialize, Deserialize)]
pub struct Config {
pub difficulty: Difficulty,
pub speed: u32,
}
impl Config {
pub fn new() -> Result<Self, std::io::Error> {
let config_path = Config::config_path().unwrap();
if config_path.exists() {
let mut config_file = File::open(config_path).unwrap();
let mut config_file_str: String = String::new();
config_file.read_to_string(&mut config_file_str).unwrap();
// let config: Config = toml::from_str(&config_file_str).expect("Error in config file");
let config: Config = match toml::from_str(&config_file_str) {
Ok(config) => config,
Err(e) => {
eprintln!(
"Error in parsing config file {} due to {}",
Config::config_path().unwrap().to_str().unwrap(),
e,
);
eprintln!("Falling back to using the default values");
sleep(std::time::Duration::from_millis(3000));
Config::default()
}
};
Ok(config)
} else {
Ok(Config::default())
}
}
fn default() -> Self {
Self {
difficulty: Difficulty::Flat, //Default set to ten blocks per second
speed: 10,
}
}
pub fn write(&self) {
let config_file_str: String = toml::to_string(self).unwrap();
let config_path = Config::config_path().unwrap();
let mut config_file: File =
File::create(config_path).expect("Couldn't open config file to write");
config_file
.write_all(config_file_str.as_bytes())
.expect("Couldn't write to file");
}
fn config_path() -> Result<PathBuf, std::io::Error> {
let config_path: PathBuf = match dirs::config_dir() {
Some(mut path) => {
path.push("snake");
path.push("snake.toml");
path
}
None => {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"snake.toml not found",
));
}
};
Ok(config_path)
}
}
+2
View File
@@ -0,0 +1,2 @@
mod backend;
pub use backend::Config;