mm26-engine's People
mm26-engine's Issues
Change "ID" fields to be tracked with a Map in GameState
Open to discussion, but I think it will be much more efficient to store IDs as the key to a Map rather than in a class itself. For example, boards are primarily accessed singularly by their board ID. If GameState had a Map from ID to Board rather than a list, this would be much easier and more efficient. And for when we need to iterate through all boards, we can still use the map.values() iterator.
This came to mind especially because I was just working on updating protos where the tagged_player_damage
map can't be from Player to double (b/c of proto limitations) but has to be from player_name to double instead. Converting this would be easy if players were stored in a Map from name to Player instance instead of in a list as well.
Important point: This only really makes sense if the ID doesn't ever matter except for getting the instance from GameState. For Board ID this is definitely true (we don't care about the ID except to retrieve the board). For Player name I'm not as sure since it's possible we would want that, though we don't have to have it either.
Thoughts? If we want to institute this change I see it affecting Board
, Character
, and GameState
.
Add move players function to game logic class
This function should allow the Position within a player and the position of the player within the board to be updated at the same time.
Add Player functionality for Item drop and pickup
Necessary for inventory management
Base Player Statistics Formulas
These need added to the getMaxHealth, getResistances, etc. In the form BASE_HEALTH + HEALTH_SCALING*level
The getLevel function also needs a formula for player level based on the stored experience.
Concurrent Modification Exception when getting request from players takes more than turn interval
jar file encounters a concurrent modification exception occasionally. Current observation is that might occur if POST requests to infra that tries to add players are received across multiple turns instead of within a single turn.
Portal fixes
We want to move "home board" tracking out of GameState
and into the spawnPoint
field in Character
. This has some implications for portals (and I have further general issues as well):
-
in
canUsePortal
the second for loop seems redundant. In this function we need to check if the player is currently on a portal. If they are, using a portal is valid. Given that, I think the first for loop covers all the cases we need. @DrewWarner please check me on this! -
in
usePortal
let's have index -1 refer home and any other index refer to a PvP Board portal. If this is true we shouldn't need any for loops! If index is -1, go to the first (and only) portal of the player'sspawnPoint
board. If the index is something else, then go to the corresponding portal of PvP Board.
Add ID to Boards
Instead of double storing Boards, we need to add an ID member to the Board class. Positions should be updated to have a Board ID member (so a position consists of board, x, and y). GameState needs a helper function to get the board corresponding to a Board ID. This function should only ever be called from GameLogic. We shouldn't need to pass the whole GameState into a (for example) Player class helper function.
Create conversion functions between proto classes and game engine classes
Since protos are somewhat limited in what information they can transfer, we've decided to have our own game engine classes which mirror the protos and deal with conversion separately. For each of these classes we need to have a constructor which takes in the proto equivalent as well as a function which returns the proto as a byte[] (by first building the proto class).
These are the following classes which need this update:
- Board and Tile
- Monster, Player, and Position
- GameState
- Clothes, Hat, Shoes, Weapon, Consumable, StatusModifier, TempStatusModifier (note that Item does NOT need this since Item is abstract)
- CharacterDecision (from PlayerDecision proto)
The proto-to-instance functions (constructors) will be used for starting a new game from a previous GameState (in case of crashes!). The CharacterDecision proto-to-instance will also be used in the main game loop (i.e. in doTurn
).
The instance-to-proto functions will be used to send out the game state to players as well as to back up the game states (so that we can start from a saved game state).
(Edited 3/29/20 because I forgot that we need conversion BOTH ways)
Where in the world do we store players
where... and why...
Add helper methods for Characters
-
Calculate Euclidean Distance
-
Pathfinder to location which moves Character as close as possible to destination
Implement a database backend for storing various objects
Objects that need to be stored:
- GameState (should this be stored by date, by turn number, by UUID, ...?)
- PlayerTurn (by player) (is this necessary?)
- VisualizerTurn
For now (either until Infra helps set up Redis or until we move to testing on larger games), default Java data structures should be fine (I hope).
Store player login time
Collision detection
definition of done
Update PlayerRequestSender to match current proto definitions
Right now the PlayerRequestSender
returns a list of PlayerDecisions. In the most recent proto repo it has been fully defined, so things may need to change from that.
Additionally, the sendPlayerRequestsAndUpdateGameState
method needs to return a Map<String, PlayerDecision> where the string is the deciding player's name.
To be clear, to solve this issue we must use protoc
to get the newest decision classes, add them into the repo, and also change the return type of the function above.
The context for this change is the doTurn
function in GameLogic
which will need to know which player is making which decision.
Update player movement functions to use new position field in Player
The movement functions are accessing the board using an out of date implementation.
Use protobuf to send objects
- either create or get protobuf sending code from both visualizer and player
- make sure it works properly via unit testing
Fix naming for Enemy
Enemy naming is misleading since other Players are technically enemies for Players. Rename to Monster?
Remove references to gold/shops/buying/selling
Buying and selling items has been removed from our design, so we need to remove all references to it. For example, a lot of items have buyPrice and sellPrice members.
StatusModifiers for each Item
- Each Item subclass needs to have a StatusModifier.
- Each Player has a TempStatusModifier for temporary effects on them like potions or weapon attacks on them.
Add onDeath functionality to Character
Players need to be able to release XP gains for the Player that killed them. Monsters need to be able to release their drops onto the map and provide XP reward.
Add board_id as a parameter in Position
The Position class should store if the player is on their private Board or the main Board
Unit Testing for Websockets
Figure out how to create client end code so that we can communicate through a websocket somehow.
Investigate Protocol Buffers
Look into documentation for protocol buffers and adding the library into our repository.
Distinguish EXP gained from Monsters and from Players
Distinguishing the EXP's would allow for an exciting score tracking feature
Initial player websocket connection should be centralized to game engine
Game engine needs to be able to receive ip addresses/way to connect to player from infra, along with the player/team's name.
- Make map from player name to ip address
- For
afterConnectionEstablished()
don't add newWebsocketSession
s, rather keep track of all of the players and their endpoints manually - Add POST endpoint from infra for getting player ip address, player name
- make
PlayerInfo
class that contains ipAddr and loginTime
Figure out what endpoints need to be made between us and infra
As title (refer to #27 for context).
- what protos are necessary for the connection?
Player (and Monster) Decision Types
Characters (players and/or monsters) can make one type of move per turn. This will be defined in a Decision object. Players will communicate their decisions via server while Monsters will have a makeDecision()
function to generate a decision based on their current circumstances.
GameLogic will then have a processDecision(GameState, gameState, Character character, Decision decision)
function to update the game state according to the effects of that decision.
Decisions can be:
- None/null [nothing happens; None enum value for protos, null value for game engine]
- Move (Position newPosition) [moves character to newPosition if valid]
- Attack (Position attackPosition) [attacks using character's equipped weapon at attackPosition if valid]
- Travel (int index) [valid if standing on a portal. Takes character to portal specified by index; -1 is home, >0 is to a portal in PvP Board]
- Drop (int index) [drops item at specified index in character's inventory]
- Equip (int index) [equips/uses item at specified index in character's inventory; swaps with currently equipped item]
- PickUp (int index) [takes item at specified index in the Tile's item list and puts in inventory if space if available]
Change speed to int
Right now characters and items have double speed values. Since we are comparing this to the length of the path list, it really should be an integer.
- This involved updates
Character
,Monster
(see TODO comment with decision making),Player
,StatusModifier
andTempStatusModifier
. If I've missed any affected classes, let me know!
Develop prototype for new player instantiation
The current idea is to create a queue of new players to be added which is pushed to by the REST handler. In the Main game loop, if the Queue is not empty, pop and process those requests before continuing on to process the turn. The processing of the requests would include adding the new player server to a list of servers to ping with PlayerCommunicator as well as add a new Player object in the GameState be done with another static method in GameLogic.
Find a library for making a client-side websocket connection
Player's inventory as Array or Arraylist
Currently keeping it as a Array, but might change to Arraylist if needed.
AWS Database Backend
Will this be RabbitMQ or another microservice or directly contacting infra?
Where should the starter packs go?
As title. In a new repo like last year?
Restructure player communication to REST
Move away from websockets for player communication so we can get a clear call-and-response type communication.
Imitate infra when doing unit tests
Issue should be closed when unit tests contain init block that imitates infra in:
- collecting IP addresses for player spawned servers
- sending POST request to spawned game engine instance
Inventory - Pickup, Drop
Currently implemented both in GameLogic and Player class, need to remove one. GameLogic functions don't have checks for some things.
Drop Item function needs to include multiple drops at a time. Need to account for that in CharacterDecision class.
Develop monster functionality
We need to implement basic functionality for monsters including:
- They target the player who has dealt the most damage to them (from the <Player, Double> map)
- They return to their home tile (probably needs to be a new instance field) if their map is empty
In general for characters, we need to implement this map properly:
- To properly update this map, we need Players to be removed from all enemies when they take a portal (ANY portal, even if it's from PvP to PvP) or die. This will probably involve a function in Character (to remove a specific player) and a function in GameLogic which will call the former function for every character (though this strategy is up for discussion if you see a problem with it!)
- On death a character must grant experience to those who have damaged it. Right now the design decision is to grant equal experience to all players who have damaged it. As a placeholder, grant experience equal to the level of the character.
The above implies some changes to Character.java:
distributeRewards
should grant XP equal to level, not equal to the character's total XPupdateDeathTicks
currently just adds to the tick counter. I would much prefer a method that I can call every single turn in GameLogic. i.e. I would like this function to check that the character is dead before incrementing the tick count. Also, it seems that the monster is only ever revived when we check its dead/alive status. This seems counter intuitive to me. Instead I would rather haveupdateDeathTicks
be turned into a generalupdate
function which updates death ticks if the monster is dead and revives it if it is time. This way theupdate
function can be called every turn by GameLogic and we can also add any new updating functionality to this method easily. (Also, theisDead
function never callsrespawn
even though it should -- this should be put intoupdate
.)
Portal implementation
How do we represent a portal that connects two zones? How does a player instruct their bot to move through a portal?
Add A* implementation for movement validation
Update movePlayers to use one Character
Update outdated function to use Character since Monsters will also need to be able to move.
Add helper function to figure out if Position is valid within board
- Most likely static function in gameLogic class
- Checks if position is within edges of board
Incorporate Memory Objects into Starter Packs
Implement Memory Object (from Infra) to both starter packs.
Investigate Web Sockets
We need to create a web socket to communicate with Visualizer. Let's look into how this works as well as whether or not we can run both our HTTP server and the web socket on the same port (see this stackoverflow).
Add helper function to let Player equip their weapon
- Check if weapon is in inventory
- Exchange weapon in weapon parameter with weapon from inventory
Re-evaluate class structure
Decide if changes need to be made to overall package/class structure.
Create Inventory Interface
We need the following functions for interacting with inventory in the Player class:
- equip(int index) // Equips the item at given index. If it's a consumable, use it.
- pickUpItem(int index) // Pick up the item at given index (from the list of items in the player's current tile). Handle cases like full inventory, etc.
- dropItem(int index) // drops item at given index onto player's current tile
Implement class structure
Forgive this ugly formatting.
Main
Board
Character
- Enemy
- Player
Game Logic
GameState
Tile
PlayerCommunicator
PlayerDecision
Inventory
Item - Consumable (has charges)
- Wearable
- Weapon
- Hat
- Shoes
- Clothes
WeaponEffect
Weapons have:
range (int)
damage (int)
effects (list)
Tiles have:
type (blank, impassible, inn, portal1, portal2... portaln)
list of items on the tile (list)
character (might be null)
Order of Decisions
This issue generally describes the order in which things should happen in doTurn
. It is all up for discussion and there are still many question!
- First, we should check which characters are alive. Dead characters' actions should be ignored and they should be removed from all
taggedPlayers
maps (See #61). (Should dead players be allowed to do inventory management actions? How long are players dead for before they respawn?) - Next we should read all the actions and sort them into 3 categories: Movement, Attacks, and Inventory Management.
- Then we should execute all actions of each category at a time (@jackducham What order should this be done in? I'll post my thoughts separately). These actions should be processed as if they were simultaneous. For example, if two players are at 1 HP and both attack each other, both should die and both should get rewards for killing the other player.
- Lastly we should update all characters (right now this just means updating death ticks if they're dead, but could include other similar things in the future).
Add intelligence to Monsters
Add the following to the Monsters class (previously Enemy class):
- private List taggedPlayers // keeps track of players who have attacked this monster (for use in granted XP rewards on death and for monster AI
- takeDamage(double damage, Player player) // take damage from the given player. Add player to taggedPlayers list
- doTurn() // some kind of AI to follow a taggedPlayer
Transfer current code structure into multi-layered data access system
Current layout (in server
package):
API layer- GameStateController
Service layer- GameStateService
Data Access Layer- GameStateDao
(along with GameStateFakeDao
and GameStateRedisDao
)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.