Giter Club home page Giter Club logo

binarymatrixplayer's People

Contributors

fayti1703 avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

binarymatrixplayer's Issues

Infinite Loop in `CardList::EnsureFreeCapacity`

This code may infinite loop:

int newLength;
do {
newLength = this.cards.Length * 2;
if(newLength == 0) newLength = 1;
} while(requiredLength > newLength);

Note that newLength never actually grows, as it keeps being reset to this.Cards.Length * 2 -- if a simple doubling of the array size doesn't result in a large enough array for the requested capacity; this code loops indefinitely.

Possible Solutions

Initialize newLength to this.Cards.Length, then change the statement in the loop to newLength *= 2;

`BinaryMatrixEngineAccessor` is incomplete

BinaryMatrixEngineAccessor has some missing/unimplemented features that would be nice to have for debugging and testing purposes, in particular:

  • A /full-state command that dumps the entire current game state to be inspected:
    #if false
    private static void DumpFullState(GameContext game) {
    throw new NotImplementedException();
    }
    #endif
  • Support for more than two players:
    /* FIXME?: This doesn't support multiple players per side yet */
  • Some form of file input to quickly restore to a game state. Luckily binmat is entirely deterministic (minus shuffles, but we use a PRNG), so seed + actions taken is enough to encode the entire game state.
  • When no file input is provided, use a random seed (make sure this is stored/displayed somewhere to allow for restores)
  • Display the binlog for the current turn in the output (Added from #8)

`GameContext::Tick` doesn't prevent ticking a finished game

There's no check for a completed game here:

public PlayerRole? Tick() {
this.hooks.PreTurn(this);
IEnumerable<Player> activePlayers = this.TurnCounter % 2 == 0 ? this.Defenders : this.Attackers;
{
List<ActionLog> actions = new();
HashSet<Cell> drawnDecks = new();
foreach((Player player, ActionSet action) in this.hooks.GetActions(this, activePlayers)) {
GameExecution.ExecutePlayerTurn(this, player, action, drawnDecks, out ActionLog actionLog);
actions.Add(actionLog);
if(this.Victor != null) break;
}
this.binlog.Add(new TurnLog(this.TurnCounter, actions));
}
if(this.Victor != null) return this.Victor;
this.hooks.PostTurn(this);
if(this.Victor != null) return this.Victor;
this.TurnCounter++;
return null;
}

Possible solution: at the top of the method, check for this.victor != null, and if so, return this.victor.

`Player.cs` is overloaded

@Engine/Player.cs has too many symbols defined inside it:

  • enum PlayerRole
  • enum ActionType
  • struct ActionSet
  • interface CardSpecification
  • struct PlayerData
  • class Player
  • interface PlayerActor
  • interface ActionablePlayerActor (deprecated)
  • struct PlayerID

At minimum, ActionType/ActionSet/CardSpecification should be moved to a separate file (this set of types is relatively isolated).

Player Action Ordering is incorrectly strict

Problem

This code here:

IEnumerable<Player> activePlayers = this.TurnCounter % 2 == 0 ? this.Defenders : this.Attackers;
{
List<ActionLog> actions = new();
HashSet<Cell> drawnDecks = new();
foreach(
(Player player, ActionSet action) in
activePlayers.Select(x => (player: x, action: x.GetAndConsumeAction()))
) {
GameExecution.ExecutePlayerTurn(this, player, action, drawnDecks, out ActionLog actionLog);
actions.Add(actionLog);
if(this.Victor != null) break;
}
this.binlog.Add(new TurnLog(this.TurnCounter, actions));
}

currently assumes that the Attackers/Defenders enumerables contain the attacking/defending players in proper action order.

However, the action order of players can change from turn to turn. It is not possible to reorder the player list in the current engine, making this impossible to implement.

Possible Solutions

  1. Add a new game hook that allows sorting the list of active players prior to action execution
  2. Change the Player/ActionSet architecture in that code to more closely resemble how the spec1 is written.
  3. Keep the current architecture, just allow sorting the player list rejected: this breaks the current PlayerID implementation.

Spec References

  • § 5.3.5. Order players and determine actions
  • § 5.3.6. Game loop, steps 8.c through 8.f

Footnotes

  1. Technically, the 'BINMAT Algorithmic Explanation'

`CardList` may need optimization

/* TODO?: Do an optimization pass over this?
* We could take advantage of the unique nature of literally *every single list* here.
* Combat Stacks: Filled one at a time, then rapidly emptied. (Defender stack might have some leftovers.)
* Lane Decks/Attacker Deck: Drained one at a time, then rapidly refilled.
* Discard Piles: Filled slowly, then rapidly emptied.
*
* (honestly optimizing this doesn't matter except for rapidly simulating games, so this is more of an academic thing)
*/

This comment was written before CardList::MoveAllTo was introduced and at a time that CardList::TakeFirst still had usages -- as such, this may be outdated. Running some benchmarks would still be good here, I think. (Particularly to figure out if this is even an area that needs attention!)


/* TODO?: Profile array pool usage to get a sense of some better parameters here. */
private static readonly ArrayPool<Card> listPool = ArrayPool<Card>.Create(8, 32);

(calls ArrayPool::Create(int maxArrayLength, int maxArraysPerBucket))

Some simple benchmarking and tracking of average list lengths, along with free/used;reused/newly allocated stats would be good here. These parameters were arbitrarily chosen by a neural network (read: I made them up) instead of any hard data.

Binlog is not implemented

The binlog is not implemented. This is an important feature to provide feedback about the game state to players.

Internal game execution operations should already be ordered in such a way that the binlog need only record them as they occur. Any situation where this is not the case should be treated as a bug.

Possible implementation

Several game execution methods will require some way to record log-relevant information. A possible implementation would be an additional out argument -- e.g. combat resolution might take an out CombatLog containing the binlog information for the resolved combat.

This would then be added to and propagated through similar structures up to the player turn execution, which would append to an array in GameContext.

GameState will also record this information.

There are no tests

All current testing was performed locally, using BinaryMatrixEngineAccessor in a terminal session. This does not scale, nor is it particularly exhaustive.

Adding some unit tests would allow for increased confidence that the code behaves correctly, particularly after changes to the internals.

Dependencies

Test Coverage is low

The current test suite has a test coverage of 45%, which is too low for proper confidence.

There are no Roslyn intents / inspections for `CardList`

This makes refactoring certain patterns hard -- e.g.

CardList cards = declval();
cards.AddRange([ new Card(EIGHT, FORM) ]);

to

CardList cards = declval();
cards.Add(new Card(EIGHT, FORM));

(should have a warning on the upper code to replace with the lower one; and an intention to do the reverse for easy adding of elements)

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.