GameObject store its own location in a tile based game? - dictionary

Making a tile based game with a MVC design pattern. In my map model I have a 2D array of all of the game objects, so that deals with location. But I do have cases when an object needs to know its own location, such as range for a spell. Is it a good idea for the object to also store its own location? I see issues with both sides.
Object does not know its own location. Location data only stored in map. If I have a location I can find an object immediately. But to go from object to location I have to iterate through an array.
Object knows it own location. Location data stored in Map and Object. If I have an active object I can just pull the location right out of the object. But this may lead to inconsistency between the map array and the object's location. I am not sure to make sure one is not updated without changing the other. I could just have each controller (object and map) have a function for moving objects, and when one is called it looks to see if the other's model is consistent and updates it. However, this seems extremely inelegant.

I'd advise you to store the location in the GameObject and make sure the locations are consistent by using private fields and a single function to modify your locations. The location could be a private member of the GameObject, and the 2D array should be a private member of the Map-class. Then you define a function in the Map-class which allows you to move the object. This function should update the array as well as the location stored in the object. How you grant the Map class access to the GameObject's location depends on the programming language. In Java you could implement a package-private function (this is the default access level) and define the Map and GameObject in the same class, in C# you could define an internal function and define the Map and GameObject in the same assembly, in C++ you could make the Map.move function a friend of the GameObject, granting it access to the protected and private members of the GameObject.
The only downside of this approach, is that you could still accidentally modify the GameObject's location within the GameObject itself, without updating the array. If you want to prevent this, you could store the location of each object in a map/Dictionary in the Map-class. In C++ this would look roughly like this:
#include<map>
class GameObject {}; //don't store the location here
struct Location {
int x,y;
};
class Map {
private:
//the 2D array containing pointers to the GameObjects
GameObject* array[WIDTH][HEIGHT];
//a map containing the locations of all the GameObjects, indexed by a pointer to them.
std::map<GameObject*,Location> locations;
public:
//move an object from a given location to another
void move( int fromX, int fromY, int toX, int toY ) {
GameObject* obj = array[fromX][fromY;
array[toX][toY] = obj
array[fromX][fromY] = 0;
locations[obj].x = toX;
locations[obj].y = toY;
}
//move a given object to a location
void move( GameObject* obj, int toX, int toY ) {
Location loc = locations[obj];
move( loc.x, loc.y, toX, toY );
}
//get the location of a given object
Location getLocation( GameObject* obj ) const {
return locations[obj];
}
};

Related

How can I retrieve struct from nested array in solidity?

I want to grab my User out of the nested gameBoard array so that I can move it to a new index set of x and y. Remix IDE throws this error: TypeError: type struct Game.User storage ref[] storage ref is not implicitly convertible to expected type struct Game.User memory. I originally tried this without the memory, but not only does that go against the goal of not storing it permanently (if I understand it correctly), but also it threw less useful errors. Please help!
pragma solidity ^0.4.0;
contract Game {
struct User{
address owner;
uint currency;
uint left;
uint right;
uint top;
uint bottom;
}
User[][10][10] public gameBoard;
function addUser (uint _x, uint _y) public {
gameBoard[_x][_y].push(User(msg.sender, 10, 5, 5, 5, 5));
}
function moveUser (uint _fromX, uint _fromY, uint _toX, uint _toY) public {
User memory mover = gameBoard[_fromX][_fromY];
if (mover.owner != msg.sender)return;
// once I have 'mover', I will check whether
// I want its the msg.senders and then place
// it where I want it to go
}
}
Short Answer: You are indexing your array wrong, and need another set of [brackets].
So you created a 3 dimensional array of users called "gameboard". When adding a user you push a struct into the dynamic 3rd dimension of your array correctly. However when you access the structs, you only give two dimensions and so Solidity returns the dynamic user array. Since you are trying to store it into a struct rather than an array of structs the error is being thrown. The easiest way to fix it is to use:
User memory mover = gameBoard[_fromX][_fromY][0];
However this only returns the first user at that position on the game board so you'll probably need to do some sort of looping (which isn't ideal in contracts). Personally I prefer to stay away from multidimensional arrays, and honestly all arrays in general (although they have their uses) when working with Solidity. Mappings are usually a lot easier to work with, especially when working with addresses. Could you possibly elaborate on what you are attempting to do in case there is a better way of achieving it?

How to bind lists like an updating ForEach?

Here is a sample code:
public class Example3 {
class Point {
int x, y; // these can be properties if it matters
}
class PointRepresentation {
Point point; // this can be a property if it matters
public PointRepresentation(Point point) {
this.point = point;
}
}
Example3() {
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = FXCollections.observableArrayList();
points.forEach(point -> representations.add(new PointRepresentation(point)));
}
}
I have a data holder Point and a data representor PointRepresentation. I have a list of points and i would like that for each point in the list there would be an equivalent representation object in the second list. The code I gave works for the initialization but if there is any change later the above will not update.
What I am doing now is using a change listener to synchronize the lists (add and remove elements based on the change object) and it's OK but i am wondering if there's a simpler solution. I was looking for something like a "for each bind" that means: for each element in one list there is one in the other with the specified relation between them [in my case its that constructor]. In pseudocode:
representations.bindForEach(points, point -> new PointRepresentation(point));
Things I looked at: extractors for the list but that sends updates when a property in the objects they hold change and not when the list itself changes. So in my case if x in the point changes i can make an extractor that notifies it. Another thing I looked at is http://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/ListBinding.html, so maybe a custom binding does it but I don't know if it's simpler.
Also is there a similar solution for arrays instead of lists? i saw the http://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableArray.html as a possibility.
The third-party library ReactFX has functionality for this. You can do
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = LiveList.map(points, PointRepresentation::new);
This will update representations automatically on add/remove etc changes to points.

Example of how to add secondary index when storing object in Riak with Java Client?

I am storing a hash-map in a riak bucket like this:
bucket.store(key, docHashMap).execute();
I would like to store the object with a secondary index.
How would I accomplish this? I am aware that the IRiakObject has a addIndex method, but how do I access the IRiakObject before it is stored?
I would think that what I am trying to do is the expected use-case, yet I am not able to find any documentation or examples on this. If you can point me to one that would be greatly appreciated.
Thanks!
Update:
#Brian Roach answered this on the Riak mailing list and below. Here is the custom class that I wrote that extends the HashMap:
class DocMap extends HashMap<String, Object> {
/**
* Generated id
*/
private static final long serialVersionUID = 5807773481499313384L;
#RiakIndex(name="status") private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
I can still use the object as an ordinary hashmap and store keys and values, but it will also write "status" to a secondary index (and actually end up being called "status_bin" since it's a string.
If you're just passing in an instance of the core Java HashMap ... you can't.
The way the default JSONConverter works for metadata (such as indexes)
is via annotations.
The object being passed in needs to have a field annotated with
#RiakIndex("index_name"). That field can be a Long/Set<Long> or
String/Set<String> (for _int and _bin indexes respectively).
These are not converted to JSON so they won't affect your serialized
data. You can have multiple fields for multiple indexes.
You don't have to append "_int" or "_bin" to the index name in the
annotation - it's done automatically based on the type.
Easiest thing to do woud be to extend HashMap and simply add the
annotated field(s).

How can I modify a value in a struct?

My struct class:
public struct PinAndRadius
{
public string pinID { get; set; }
public string radiusID { get; set; }
public string getPinID()
{
return pinID;
}
public string getRadiusID()
{
return radiusID;
}
}
the method with a problem:
void mapArea_VE_PinDragged(double latitude, double longitude, object id)
{
foreach (var pin in pinRadiusCollection)
{
string ID = id.ToString();
//string newID = ID.Substring(0, 18);
if (!pin.Key.pinID.Equals(ID))
{
continue;
}
else if (pin.Key.pinID.Equals(ID))
{
var newLoc = createNewSearchLocation(latitude, longitude);
mapArea.VE_DeleteRadius(pin.Key.radiusID);
drawPoly(newLoc, pin.Value.xar_Radius);
pin.Key.radiusID = pollyID;
break;
}
}
}
The problem is that when I try to set pin.key.radiusID to pollyID, I get an error saying
Cannot modify the return value of 'System.Collections.Generic.KeyValuePair.Key' because it is not a variable...
Any ideas?
Structure in .net is value-type. This mean you can't get reference to PinAndRadius using pin.Key. You will get copy of pin.Key of type PinAndRadius. Then you haven't access to this copy and compiler tell you about this. In C++ terms it not l-value.
If you create struct always try make it immutable. Mutable structs are evil.
Simplest way to solve this problem is to make PinAndRadius as class.
By the looks of it, your pinRadiusCollection is a generic dictionary keyed by PinAndRadius; the error you're getting is letting you know you can't modify that object because it's being used as the key in your dictionary.
If your pins are supposed to be mutable, you should probably revisit how you're storing them.
Collections in .net are not set up to allow convenient modification of struct-type items contained therein. Despite this, mutable structs still offer cleaner semantics than any other kind of data type. To edit a struct held in a collection, simply copy it to a variable, edit that variable, and store it back:
var temp = myList[someIndex];
temp.SomeVield = whatEver;
myList[someIndex] = temp;
Note that it's generally better to have mutable structs expose their contents as fields than as properties. Some people may say mutable structs are evil because their semantics differ from classes, but that's like saying screwdrivers are evil because they make lousy hammers. Exposed-field structs don't work like class types, but structs where all fields are exposed all have the same semantics as each other. Those semantics differ from classes, but for cases where they're useful, they have no equal.
Incidentally, much of the bad reps "mutable structs" got was a result of the fact that mutating struct members other than exposed fields would often generate bogus code if applied to read-only structures. If you avoid having struct members which modify fields of this [it's perfectly safe for static struct methods to modify fields of structures received as ref parameters], those dangers don't apply.
I simply just changed the struct definition to a class.

Making a reference-counted object in D using RefCounted!(T)

How do you use std.typecons.RefCounted!(T) to make a reference-counted object in D?
I've tried to figure out what std.array.Array does internally by looking at the source, but while I can read the source, I just can't figure what a "payload" is or how it all works when there's things like bitwise struct copying involved, as well as why some things are duplicated in the internal and external structure.
Could anyone provide an example or a link on how to use it to, say, wrap a simple Win32 HANDLE?
Thanks!
Disclaimer: I haven't tested my claims, just read the documentation.
Payload is referring to what is being stored. In your case the payload is the Win32 HANDLE. Since HANDLE is just an integer you wouldn't want to do:
auto refHandle = RefCounted!HANDLE(WhatGetsMeAHandle());
Because a Windows function will need to be called when the handle goes out of scope.
In std.containers.Array what you saw was a struct called Payload, which had a field called _payload. The structure is going to be the storage of the data, accessed through _payload. This provides a level of indirection to be utilized later.
You will notice that RefCounted is actually used on the Array structure. This means the destructor for that struct will only be called when the reference count is 0. So the ~this() inside of Payload is where you would want to clean up the your HANDLE.
What is happening: since struct is a value type, every time the structure goes out of scope the destructor is called, there isn't one for Array, but Payload is wrapped in a RefCounted, the destructor for RefCounted!Payload is also called. And only when the reference count reaches zero is the destructor for Payload itself called.
Now, RefCounted itself has reference semantics, this means that having an Array a, you can then assign to auto b = a; and everything will be copied over, but RefCounted has a postblits defined meaning the data will not be copied, but the reference count will be
incremented.
I will now try and provide you with a wrapper outline for what you want. It will probably help you visualize the information above, but it may not be entirely correct. Let me know if something needs fixing.
struct MyWinWrapper {
struct Payload {
HANDLE _payload;
this(HANDLE h) { _payload = h; }
~this() { freeHandleHere(_payload); }
// Should never perform these operations
this(this) { assert(false); }
void opAssign(MyWinWrapper.Payload rhs) { assert(false); }
}
private alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data;
private Data _data;
this(HANDLE h) { _data = Data(h); }
}
Since there is no default constructor for a struct you will probably want to provide a free function that returns this structure.

Resources