Giter Club home page Giter Club logo

tetrs's People

Stargazers

 avatar Daniel M. Capella avatar IntrepidPig avatar

Watchers

James Cloos avatar Marc Tiehuis avatar  avatar

tetrs's Issues

Time-based statistics

Statistics should have a time associated with them so we can construct time-based charts of a games lifetime.

Events can then be updated on the engine though something such as engine.note_event(Event::Tetris). This can then call statistics.add_event(engine.ticks, Event::Tetris) which would save the particular event in the queue of events.

Events could be stored in a complete vector, however it may also be useful to subdivide events into their own arrays as well if we require repeated querying and need a more performant structure.

The initial implementation should just iterate through a vector of events (ordered by when they occurred) and count them this way.

Another bonus is that this removes the number of different fields required for the statistics struct, and we can instead rely on a single event vector (minus some special-case events like time etc).

This should still remain separate from the history struct, since this is dealing with input events as compared to the statistics game events.

Incorrect SRS wallkick movement

SRS rotations are not as expected using "srs" rotation and wallkick settings. This was correct in an earlier revision, but this was (unfortunately) before any tests were specified.

Verify internal type casting

The interface exposed uses a mix of usize and i32 types depending on the function. Internally there is a fair bit of casting between the two and it is likely that there could be some unforeseen errors on some inputs.

It could be a thought to change over to only signed types for simplicity, but then we do not get compile-time restrictions on various input. Rust's required explicit casting should be ample enough warning for wrong input anyway.

Have proper block counters on an engine

We require a number of specific timers on each block for things such as gravity, lock delay and any other delay that is encountered. This needs to be decided whether or not to exist on an actual block instance (leaning against) or having another struct which is managed by the engine which manages these timers. This could also hold other timers unrelated to a block as well, such as ARE countdown etc.

Finalize constructor initialization patterns

As an example, an Engine requires a number of fields (Randomizer, Wallkick, Field) each of which have their own optional arguments.

These could likely be replaced with some type of builder pattern to limit the number of possible constructor calls. The default parameters need to be determined however). For example, would a be required to be tied to a field or is this optional?

Block data is not abstract enough

Currently we use one set of block data with fixed rotations. If another rotation system is wanted, this would require refactoring the current block data to use this.

We should instead hide this behind some common interface like wallkick and randomizer do currently. It is still undecided yet how to implement this, do we take an argument for the rotation type on block creation, for example?

Module for writing AI opponents

Being able to write AI opponents would be interesting.

What would be helpful for this is a module which provides some convenience functions for moving the piece to the specified location and determining whether or not moves are possible based on the current ruleset.

Extending this to allow for machine learning algorithms would be of interest also.

Loading from configuration file

It would be useful to load an engine state from a configuration file. On this note, it is also a question on how we want to structure initialization of structures. For example, would we store field options separately and if so how do we initialization a field from a json array? One possibility would be having separate Options structures in place of the builder functions present, and use these for initialization.

let field = Field::new(FieldOptions { width: 9, height: 20, ..Default::default() });

Using default fields makes this fairly nice, and it would work nicely with serialization. Further, this supports adding of new fields much easier and ensures the builder functions aren't called on constructed instances. This is quite appealing and would be worth exploring before putting configuration loading in.

This would likely apply to Field and Engine structures for the moment, as these require the most internal options.

One downside is that initialization of default parameters is more cumbersome, but since Field and Engine initialization is limited, this may be worthwhile.

let engine = Engine {
    field: Field { FieldOptions { width: 9, ..Default::default() },
    options: Options { das: 130, ..Default::default() },
    randomizer: randomizer::new("SRS", 8)
}

Remove Serde requirement for loading of deserializing game options

Serde is only used for serializing GameSettings and inhibits compilation time plus adds another dependency on a nightly feature that can be avoided.

This should be removed and managed manually. We only require serialization of a game engine settings itself, and doing it manually allows us to structure the input/output slightly differently (i.e. group randomizer options as an object etc).

Add a C library interface

A C api would be an interesting addition to provide. Partly as a learning exercise, but it would beneficial for interfacing from different languages.

This can be written directly in rust.

Handling non-divisible tick actions

Currently we can specify the required internal ms rate per frame which is nice, however when specifying DAS and other options as milliseconds, we technically can only get a minimum granularity based on the tick rate.

For example, if the tick rate was 16ms and lock delay was set to 31ms, this would occur every frame and be rounded down to 16ms.

This may just be an inherent limitation in the current engine. There are ways to improve this, such as having actions occurring at odd intervals, however this may introduce some unneeded complexity and make the internal code harder to reason about.

This is only a minor limitation, as we still gain on a traditional 60hz gameplay anyway.

Replay data and game report

Saving replay data would be great. This is already partially done in another branch, but storing the game options and how these were changed over time is required.

This would require computing a list of events (input and state changes) and being able to replay these.

We could just rely on input events if we could duplicate the rule, and this would likely be the more prudent way of going about it.

Finalize randomizer API design

Currently lookahead in the Randomizer structs are managed internally. This is quite nice from an API perspective, but adds extra complexity (and potential overhead?) to the underlying mechanisms required.

In particular, preview lookaheads would be required to be fixed length, or at least have some extra parameter to specify the lookahead provided.

The main question is whether a preview lookahead buffer should be found internally in each Randomizer or whether this is the callers responsibility.

If I can find a way to perform a generic impl for every randomizer class, I would most definitely put it as part of each Randomizer, but this may prove slightly tricky in the current stage (no inheritance).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.