|
@@ -22,10 +22,10 @@ const std = @import("std");
|
|
// health, experience) are all values of a particular size. Add them
|
|
// health, experience) are all values of a particular size. Add them
|
|
// together and you have the size of the struct as a whole.
|
|
// together and you have the size of the struct as a whole.
|
|
|
|
|
|
-const Character = struct {
|
|
|
|
- gold: u32 = 0,
|
|
|
|
- health: u8 = 100,
|
|
|
|
- experience: u32 = 0,
|
|
|
|
|
|
+const Character = struct{
|
|
|
|
+ gold: u32 = 0,
|
|
|
|
+ health: u8 = 100,
|
|
|
|
+ experience: u32 = 0,
|
|
};
|
|
};
|
|
|
|
|
|
// Here we create a character called "the_narrator" that is a constant
|
|
// Here we create a character called "the_narrator" that is a constant
|
|
@@ -35,9 +35,9 @@ const Character = struct {
|
|
// memory is hard-coded and neither the address nor the value changes.
|
|
// memory is hard-coded and neither the address nor the value changes.
|
|
|
|
|
|
const the_narrator = Character{
|
|
const the_narrator = Character{
|
|
- .gold = 12,
|
|
|
|
- .health = 99,
|
|
|
|
- .experience = 9000,
|
|
|
|
|
|
+ .gold = 12,
|
|
|
|
+ .health = 99,
|
|
|
|
+ .experience = 9000,
|
|
};
|
|
};
|
|
|
|
|
|
// This "global_wizard" character is very similar. The address for
|
|
// This "global_wizard" character is very similar. The address for
|
|
@@ -59,118 +59,118 @@ var global_wizard = Character{};
|
|
// Our main() function here has no input parameters, but it will have
|
|
// Our main() function here has no input parameters, but it will have
|
|
// a stack entry (called a "frame").
|
|
// a stack entry (called a "frame").
|
|
|
|
|
|
-pub fn main() void {
|
|
|
|
-
|
|
|
|
- // Here, the "glorp" character will be allocated on the stack
|
|
|
|
- // because each instance of glorp is mutable and therefore unique
|
|
|
|
- // to the invocation of this function.
|
|
|
|
-
|
|
|
|
- var glorp = Character{
|
|
|
|
- .gold = 30,
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // The "reward_xp" value is interesting. It's an immutable
|
|
|
|
- // value, so even though it is local, it can be put in global
|
|
|
|
- // data and shared between all invocations. But being such a
|
|
|
|
- // small value, it may also simply be inlined as a literal
|
|
|
|
- // value in your instruction code where it is used. It's up
|
|
|
|
- // to the compiler.
|
|
|
|
-
|
|
|
|
- const reward_xp: u32 = 200;
|
|
|
|
-
|
|
|
|
- // Now let's circle back around to that "std" struct we imported
|
|
|
|
- // at the top. Since it's just a regular Zig value once it's
|
|
|
|
- // imported, we can also assign new names for its fields and
|
|
|
|
- // declarations. "debug" refers to another struct and "print" is a
|
|
|
|
- // public function namespaced within THAT struct.
|
|
|
|
- //
|
|
|
|
- // Let's assign the std.debug.print function to a const named
|
|
|
|
- // "print" so that we can use this new name later!
|
|
|
|
-
|
|
|
|
- const print = ???;
|
|
|
|
-
|
|
|
|
- // Now let's look at assigning and pointing to values in Zig.
|
|
|
|
- //
|
|
|
|
- // We'll try three different ways of making a new name to access
|
|
|
|
- // our glorp Character and change one of its values.
|
|
|
|
- //
|
|
|
|
- // "glorp_access1" is incorrectly named! We asked Zig to set aside
|
|
|
|
- // memory for another Character struct. So when we assign glorp to
|
|
|
|
- // glorp_access1 here, we're actually assigning all of the fields
|
|
|
|
- // to make a copy! Now we have two separate characters.
|
|
|
|
- //
|
|
|
|
- // You don't need to fix this. But notice what gets printed in
|
|
|
|
- // your program's output for this one compared to the other two
|
|
|
|
- // assignments below!
|
|
|
|
-
|
|
|
|
- var glorp_access1: Character = glorp;
|
|
|
|
- glorp_access1.gold = 111;
|
|
|
|
- print("1:{}!. ", .{glorp.gold == glorp_access1.gold});
|
|
|
|
-
|
|
|
|
- // NOTE:
|
|
|
|
- //
|
|
|
|
- // If we tried to do this with a const Character instead of a
|
|
|
|
- // var, changing the gold field would give us a compiler error
|
|
|
|
- // because const values are immutable!
|
|
|
|
- //
|
|
|
|
- // "glorp_access2" will do what we want. It points to the original
|
|
|
|
- // glorp's address. Also remember that we get one implicit
|
|
|
|
- // dereference with struct fields, so accessing the "gold" field
|
|
|
|
- // from glorp_access2 looks just like accessing it from glorp
|
|
|
|
- // itself.
|
|
|
|
-
|
|
|
|
- var glorp_access2: *Character = &glorp;
|
|
|
|
- glorp_access2.gold = 222;
|
|
|
|
- print("2:{}!. ", .{glorp.gold == glorp_access2.gold});
|
|
|
|
-
|
|
|
|
- // "glorp_access3" is interesting. It's also a pointer, but it's a
|
|
|
|
- // const. Won't that disallow changing the gold value? No! As you
|
|
|
|
- // may recall from our earlier pointer experiments, a constant
|
|
|
|
- // pointer can't change what it's POINTING AT, but the value at
|
|
|
|
- // the address it points to is still mutable! So we CAN change it.
|
|
|
|
-
|
|
|
|
- const glorp_access3: *Character = &glorp;
|
|
|
|
- glorp_access3.gold = 333;
|
|
|
|
- print("3:{}!. ", .{glorp.gold == glorp_access3.gold});
|
|
|
|
-
|
|
|
|
- // NOTE:
|
|
|
|
- //
|
|
|
|
- // If we tried to do this with a *const Character pointer,
|
|
|
|
- // that would NOT work and we would get a compiler error
|
|
|
|
- // because the VALUE becomes immutable!
|
|
|
|
- //
|
|
|
|
- // Moving along...
|
|
|
|
- //
|
|
|
|
- // When arguments are passed to a function,
|
|
|
|
- // they are ALWAYS passed as constants within the function,
|
|
|
|
- // regardless of how they were declared in the calling function.
|
|
|
|
- //
|
|
|
|
- // Example:
|
|
|
|
- // fn foo(arg: u8) void {
|
|
|
|
- // arg = 42; // Error, 'arg' is const!
|
|
|
|
- // }
|
|
|
|
- //
|
|
|
|
- // fn bar() void {
|
|
|
|
- // var arg: u8 = 12;
|
|
|
|
- // foo(arg);
|
|
|
|
- // ...
|
|
|
|
- // }
|
|
|
|
- //
|
|
|
|
- // Knowing this, see if you can make levelUp() work as expected -
|
|
|
|
- // it should add the specified amount to the supplied character's
|
|
|
|
- // experience points.
|
|
|
|
- //
|
|
|
|
- print("XP before:{}, ", .{glorp.experience});
|
|
|
|
-
|
|
|
|
- // Fix 1 of 2 goes here:
|
|
|
|
- levelUp(glorp, reward_xp);
|
|
|
|
-
|
|
|
|
- print("after:{}.\n", .{glorp.experience});
|
|
|
|
|
|
+pub fn main() void{
|
|
|
|
+
|
|
|
|
+ // Here, the "glorp" character will be allocated on the stack
|
|
|
|
+ // because each instance of glorp is mutable and therefore unique
|
|
|
|
+ // to the invocation of this function.
|
|
|
|
+
|
|
|
|
+ var glorp = Character{
|
|
|
|
+ .gold = 30,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // The "reward_xp" value is interesting. It's an immutable
|
|
|
|
+ // value, so even though it is local, it can be put in global
|
|
|
|
+ // data and shared between all invocations. But being such a
|
|
|
|
+ // small value, it may also simply be inlined as a literal
|
|
|
|
+ // value in your instruction code where it is used. It's up
|
|
|
|
+ // to the compiler.
|
|
|
|
+
|
|
|
|
+ const reward_xp: u32 = 200;
|
|
|
|
+
|
|
|
|
+ // Now let's circle back around to that "std" struct we imported
|
|
|
|
+ // at the top. Since it's just a regular Zig value once it's
|
|
|
|
+ // imported, we can also assign new names for its fields and
|
|
|
|
+ // declarations. "debug" refers to another struct and "print" is a
|
|
|
|
+ // public function namespaced within THAT struct.
|
|
|
|
+ //
|
|
|
|
+ // Let's assign the std.debug.print function to a const named
|
|
|
|
+ // "print" so that we can use this new name later!
|
|
|
|
+
|
|
|
|
+ const print = std.debug.print;
|
|
|
|
+
|
|
|
|
+ // Now let's look at assigning and pointing to values in Zig.
|
|
|
|
+ //
|
|
|
|
+ // We'll try three different ways of making a new name to access
|
|
|
|
+ // our glorp Character and change one of its values.
|
|
|
|
+ //
|
|
|
|
+ // "glorp_access1" is incorrectly named! We asked Zig to set aside
|
|
|
|
+ // memory for another Character struct. So when we assign glorp to
|
|
|
|
+ // glorp_access1 here, we're actually assigning all of the fields
|
|
|
|
+ // to make a copy! Now we have two separate characters.
|
|
|
|
+ //
|
|
|
|
+ // You don't need to fix this. But notice what gets printed in
|
|
|
|
+ // your program's output for this one compared to the other two
|
|
|
|
+ // assignments below!
|
|
|
|
+
|
|
|
|
+ var glorp_access1: Character = glorp;
|
|
|
|
+ glorp_access1.gold = 111;
|
|
|
|
+ print("1:{}!. ", .{glorp.gold == glorp_access1.gold});
|
|
|
|
+
|
|
|
|
+ // NOTE:
|
|
|
|
+ //
|
|
|
|
+ // If we tried to do this with a const Character instead of a
|
|
|
|
+ // var, changing the gold field would give us a compiler error
|
|
|
|
+ // because const values are immutable!
|
|
|
|
+ //
|
|
|
|
+ // "glorp_access2" will do what we want. It points to the original
|
|
|
|
+ // glorp's address. Also remember that we get one implicit
|
|
|
|
+ // dereference with struct fields, so accessing the "gold" field
|
|
|
|
+ // from glorp_access2 looks just like accessing it from glorp
|
|
|
|
+ // itself.
|
|
|
|
+
|
|
|
|
+ var glorp_access2: *Character = &glorp;
|
|
|
|
+ glorp_access2.gold = 222;
|
|
|
|
+ print("2:{}!. ", .{glorp.gold == glorp_access2.gold});
|
|
|
|
+
|
|
|
|
+ // "glorp_access3" is interesting. It's also a pointer, but it's a
|
|
|
|
+ // const. Won't that disallow changing the gold value? No! As you
|
|
|
|
+ // may recall from our earlier pointer experiments, a constant
|
|
|
|
+ // pointer can't change what it's POINTING AT, but the value at
|
|
|
|
+ // the address it points to is still mutable! So we CAN change it.
|
|
|
|
+
|
|
|
|
+ const glorp_access3: *Character = &glorp;
|
|
|
|
+ glorp_access3.gold = 333;
|
|
|
|
+ print("3:{}!. ", .{glorp.gold == glorp_access3.gold});
|
|
|
|
+
|
|
|
|
+ // NOTE:
|
|
|
|
+ //
|
|
|
|
+ // If we tried to do this with a *const Character pointer,
|
|
|
|
+ // that would NOT work and we would get a compiler error
|
|
|
|
+ // because the VALUE becomes immutable!
|
|
|
|
+ //
|
|
|
|
+ // Moving along...
|
|
|
|
+ //
|
|
|
|
+ // When arguments are passed to a function,
|
|
|
|
+ // they are ALWAYS passed as constants within the function,
|
|
|
|
+ // regardless of how they were declared in the calling function.
|
|
|
|
+ //
|
|
|
|
+ // Example:
|
|
|
|
+ // fn foo(arg: u8) void {
|
|
|
|
+ // arg = 42; // Error, 'arg' is const!
|
|
|
|
+ // }
|
|
|
|
+ //
|
|
|
|
+ // fn bar() void {
|
|
|
|
+ // var arg: u8 = 12;
|
|
|
|
+ // foo(arg);
|
|
|
|
+ // ...
|
|
|
|
+ // }
|
|
|
|
+ //
|
|
|
|
+ // Knowing this, see if you can make levelUp() work as expected -
|
|
|
|
+ // it should add the specified amount to the supplied character's
|
|
|
|
+ // experience points.
|
|
|
|
+ //
|
|
|
|
+ print("XP before:{}, ", .{glorp.experience});
|
|
|
|
+
|
|
|
|
+ // Fix 1 of 2 goes here:
|
|
|
|
+ levelUp(&glorp, reward_xp);
|
|
|
|
+
|
|
|
|
+ print("after:{}.\n", .{glorp.experience});
|
|
}
|
|
}
|
|
|
|
|
|
// Fix 2 of 2 goes here:
|
|
// Fix 2 of 2 goes here:
|
|
-fn levelUp(character_access: Character, xp: u32) void {
|
|
|
|
- character_access.experience += xp;
|
|
|
|
|
|
+fn levelUp(character_access: *Character, xp: u32) void{
|
|
|
|
+ character_access.experience += xp;
|
|
}
|
|
}
|
|
|
|
|
|
// And there's more!
|
|
// And there's more!
|
|
@@ -193,3 +193,4 @@ fn levelUp(character_access: Character, xp: u32) void {
|
|
// Whew! This has been a lot of information. You'll be pleased to know
|
|
// Whew! This has been a lot of information. You'll be pleased to know
|
|
// that the next exercise gets us back to learning Zig language
|
|
// that the next exercise gets us back to learning Zig language
|
|
// features we can use right away to do more things!
|
|
// features we can use right away to do more things!
|
|
|
|
+
|